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"
38 #include "tcuVector.hpp"
39 #include "tcuMaybe.hpp"
40 #include "tcuTestLog.hpp"
41 #include "tcuVectorUtil.hpp"
43 #include "deUniquePtr.hpp"
44 #include "deStringUtil.hpp"
61 inline vk::VkBool32 makeVkBool32(bool value)
63 return (value ? VK_TRUE : VK_FALSE);
67 constexpr deUint32 kFramebufferWidth = 64u;
68 constexpr deUint32 kFramebufferHeight = 64u;
71 constexpr vk::VkFormat kColorFormat = vk::VK_FORMAT_R8G8B8A8_UNORM;
72 constexpr vk::VkFormat kDepthStencilFormat = vk::VK_FORMAT_D32_SFLOAT_S8_UINT;
73 const tcu::Vec4 kColorThreshold (0.005f); // 1/255 < 0.005 < 2/255.
75 // Vertices in buffers will have 2 components and a padding to properly test the stride.
81 GeometryVertex (const tcu::Vec2& coords_)
88 constexpr auto kVertexStride = static_cast<vk::VkDeviceSize>(sizeof(GeometryVertex));
89 constexpr auto kCoordsSize = static_cast<vk::VkDeviceSize>(sizeof(GeometryVertex::coords));
91 // Stencil Operation parameters, as used in vkCmdSetStencilOpEXT().
92 struct StencilOpParams
94 vk::VkStencilFaceFlags faceMask;
95 vk::VkStencilOp failOp;
96 vk::VkStencilOp passOp;
97 vk::VkStencilOp depthFailOp;
98 vk::VkCompareOp compareOp;
101 const StencilOpParams kDefaultStencilOpParams =
103 vk::VK_STENCIL_FACE_FRONT_AND_BACK,
104 vk::VK_STENCIL_OP_KEEP,
105 vk::VK_STENCIL_OP_KEEP,
106 vk::VK_STENCIL_OP_KEEP,
107 vk::VK_COMPARE_OP_ALWAYS
110 using ViewportVec = std::vector<vk::VkViewport>;
111 using ScissorVec = std::vector<vk::VkRect2D>;
112 using StencilOpVec = std::vector<StencilOpParams>;
114 // Generic, to be used with any state than can be set statically and, as an option, dynamically.
116 struct StaticAndDynamicPair
119 tcu::Maybe<T> dynamicValue;
121 // Helper constructor to set a static value and no dynamic value.
122 StaticAndDynamicPair (const T& value)
123 : staticValue (value)
124 , dynamicValue (tcu::nothing<T>())
128 // Helper constructor to set both.
129 StaticAndDynamicPair (const T& sVal, const T& dVal)
131 , dynamicValue (tcu::just<T>(dVal))
136 // For anything boolean, see below.
137 using BooleanFlagConfig = StaticAndDynamicPair<bool>;
139 // Configuration for every aspect of the extended dynamic state.
140 using CullModeConfig = StaticAndDynamicPair<vk::VkCullModeFlags>;
141 using FrontFaceConfig = StaticAndDynamicPair<vk::VkFrontFace>;
142 using TopologyConfig = StaticAndDynamicPair<vk::VkPrimitiveTopology>;
143 using ViewportConfig = StaticAndDynamicPair<ViewportVec>; // At least one element.
144 using ScissorConfig = StaticAndDynamicPair<ScissorVec>; // At least one element.
145 using StrideConfig = StaticAndDynamicPair<vk::VkDeviceSize>;
146 using DepthTestEnableConfig = BooleanFlagConfig;
147 using DepthWriteEnableConfig = BooleanFlagConfig;
148 using DepthCompareOpConfig = StaticAndDynamicPair<vk::VkCompareOp>;
149 using DepthBoundsTestEnableConfig = BooleanFlagConfig;
150 using StencilTestEnableConfig = BooleanFlagConfig;
151 using StencilOpConfig = StaticAndDynamicPair<StencilOpVec>; // At least one element.
153 const tcu::Vec4 kDefaultTriangleColor (0.0f, 0.0f, 1.0f, 1.0f); // Opaque blue.
154 const tcu::Vec4 kDefaultClearColor (0.0f, 0.0f, 0.0f, 1.0f); // Opaque black.
166 MeshParams (const tcu::Vec4& color_ = kDefaultTriangleColor,
168 bool reversed_ = false,
169 float scaleX_ = 1.0f,
170 float scaleY_ = 1.0f,
171 float offsetX_ = 0.0f,
172 float offsetY_ = 0.0f)
175 , reversed (reversed_)
183 enum class SequenceOrdering
185 CMD_BUFFER_START = 0, // Set state at the start of the command buffer.
186 BEFORE_DRAW = 1, // After binding dynamic pipeline and just before drawing.
187 BETWEEN_PIPELINES = 2, // After a static state pipeline has been bound but before the dynamic state pipeline has been bound.
188 AFTER_PIPELINES = 3, // After a static state pipeline and a second dynamic state pipeline have been bound.
193 // Main sequence ordering.
194 SequenceOrdering sequenceOrdering;
196 // Drawing parameters: tests will draw one or more flat meshes of triangles covering the whole "screen".
197 std::vector<MeshParams> meshParams; // Mesh parameters for each full-screen layer of geometry.
198 deUint32 referenceStencil; // Reference stencil value.
200 // Clearing parameters for the framebuffer.
201 tcu::Vec4 clearColorValue;
202 float clearDepthValue;
203 deUint32 clearStencilValue;
205 // Expected output in the attachments.
206 tcu::Vec4 expectedColor;
208 deUint32 expectedStencil;
210 // Depth bounds parameters for the pipeline.
211 float minDepthBounds;
212 float maxDepthBounds;
214 // Include passthrough geometry shader or not.
215 bool useGeometryShader;
217 // Static and dynamic pipeline configuration.
218 CullModeConfig cullModeConfig;
219 FrontFaceConfig frontFaceConfig;
220 TopologyConfig topologyConfig;
221 ViewportConfig viewportConfig;
222 ScissorConfig scissorConfig;
223 StrideConfig strideConfig;
224 DepthTestEnableConfig depthTestEnableConfig;
225 DepthWriteEnableConfig depthWriteEnableConfig;
226 DepthCompareOpConfig depthCompareOpConfig;
227 DepthBoundsTestEnableConfig depthBoundsTestEnableConfig;
228 StencilTestEnableConfig stencilTestEnableConfig;
229 StencilOpConfig stencilOpConfig;
232 TestConfig (SequenceOrdering ordering)
233 : sequenceOrdering (ordering)
234 , meshParams (1u, MeshParams())
235 , referenceStencil (0u)
236 , clearColorValue (kDefaultClearColor)
237 , clearDepthValue (1.0f)
238 , clearStencilValue (0u)
239 , expectedColor (kDefaultTriangleColor)
240 , expectedDepth (1.0f)
241 , expectedStencil (0u)
242 , minDepthBounds (0.0f)
243 , maxDepthBounds (1.0f)
244 , useGeometryShader (false)
245 , cullModeConfig (static_cast<vk::VkCullModeFlags>(vk::VK_CULL_MODE_NONE))
246 , frontFaceConfig (vk::VK_FRONT_FACE_COUNTER_CLOCKWISE)
247 // By default we will use a triangle fan with 6 vertices that could be wrongly interpreted as a triangle list with 2 triangles.
248 , topologyConfig (vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN)
249 , viewportConfig (ViewportVec(1u, vk::makeViewport(kFramebufferWidth, kFramebufferHeight)))
250 , scissorConfig (ScissorVec(1u, vk::makeRect2D(kFramebufferWidth, kFramebufferHeight)))
251 , strideConfig (kVertexStride)
252 , depthTestEnableConfig (false)
253 , depthWriteEnableConfig (false)
254 , depthCompareOpConfig (vk::VK_COMPARE_OP_NEVER)
255 , depthBoundsTestEnableConfig (false)
256 , stencilTestEnableConfig (false)
257 , stencilOpConfig (StencilOpVec(1u, kDefaultStencilOpParams))
264 tcu::Vec4 triangleColor;
266 deInt32 viewPortIndex;
273 void copy(vk::VkStencilOpState& dst, const StencilOpParams& src)
275 dst.failOp = src.failOp;
276 dst.passOp = src.passOp;
277 dst.depthFailOp = src.depthFailOp;
278 dst.compareOp = src.compareOp;
281 enum class TopologyClass
290 std::string topologyClassName (TopologyClass tclass)
294 case TopologyClass::POINT: return "point";
295 case TopologyClass::LINE: return "line";
296 case TopologyClass::TRIANGLE: return "triangle";
297 case TopologyClass::PATCH: return "patch";
306 TopologyClass getTopologyClass (vk::VkPrimitiveTopology topology)
310 case vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
311 return TopologyClass::POINT;
312 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
313 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
314 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
315 case vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
316 return TopologyClass::LINE;
317 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
318 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
319 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
320 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
321 case vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
322 return TopologyClass::TRIANGLE;
323 case vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST:
324 return TopologyClass::PATCH;
330 return TopologyClass::INVALID;
333 class ExtendedDynamicStateTest : public vkt::TestCase
336 ExtendedDynamicStateTest (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const TestConfig& testConfig);
337 virtual ~ExtendedDynamicStateTest (void) {}
339 virtual void checkSupport (Context& context) const;
340 virtual void initPrograms (vk::SourceCollections& programCollection) const;
341 virtual TestInstance* createInstance (Context& context) const;
344 TestConfig m_testConfig;
347 class ExtendedDynamicStateInstance : public vkt::TestInstance
350 ExtendedDynamicStateInstance (Context& context, const TestConfig& testConfig);
351 virtual ~ExtendedDynamicStateInstance (void) {}
353 virtual tcu::TestStatus iterate (void);
356 TestConfig m_testConfig;
359 ExtendedDynamicStateTest::ExtendedDynamicStateTest (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const TestConfig& testConfig)
360 : vkt::TestCase (testCtx, name, description)
361 , m_testConfig (testConfig)
363 const auto staticTopologyClass = getTopologyClass(testConfig.topologyConfig.staticValue);
364 DE_UNREF(staticTopologyClass); // For release builds.
366 // Matching topology classes.
367 DE_ASSERT(!testConfig.topologyConfig.dynamicValue ||
368 staticTopologyClass == getTopologyClass(testConfig.topologyConfig.dynamicValue.get()));
370 // Supported topology classes for these tests.
371 DE_ASSERT(staticTopologyClass == TopologyClass::LINE || staticTopologyClass == TopologyClass::TRIANGLE);
374 void ExtendedDynamicStateTest::checkSupport (Context& context) const
376 const auto& vki = context.getInstanceInterface();
377 const auto physicalDevice = context.getPhysicalDevice();
379 // This is always required.
380 context.requireDeviceFunctionality("VK_EXT_extended_dynamic_state");
382 // Check the number of viewports needed and the corresponding limits.
383 const auto& viewportConfig = m_testConfig.viewportConfig;
384 auto numViews = viewportConfig.staticValue.size();
386 if (viewportConfig.dynamicValue)
387 numViews = std::max(numViews, viewportConfig.dynamicValue.get().size());
391 context.requireDeviceFunctionality("VK_KHR_multiview");
392 const auto properties = vk::getPhysicalDeviceProperties(vki, physicalDevice);
393 if (numViews > static_cast<decltype(numViews)>(properties.limits.maxViewports))
394 TCU_THROW(NotSupportedError, "Number of viewports not supported (" + de::toString(numViews) + ")");
397 const auto& dbTestEnable = m_testConfig.depthBoundsTestEnableConfig;
398 const bool useDepthBounds = (dbTestEnable.staticValue || (dbTestEnable.dynamicValue && dbTestEnable.dynamicValue.get()));
399 if (useDepthBounds || m_testConfig.useGeometryShader)
401 const auto features = vk::getPhysicalDeviceFeatures(vki, physicalDevice);
403 // Check depth bounds test support.
404 if (useDepthBounds && !features.depthBounds)
405 TCU_THROW(NotSupportedError, "Depth bounds feature not supported");
407 // Check geometry shader support.
408 if (m_testConfig.useGeometryShader && !features.geometryShader)
409 TCU_THROW(NotSupportedError, "Geometry shader not supported");
412 // Check image format support.
413 const vk::VkFormatFeatureFlags kColorFeatures = (vk::VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | vk::VK_FORMAT_FEATURE_TRANSFER_SRC_BIT);
414 const vk::VkFormatFeatureFlags kDSFeatures = (vk::VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT | vk::VK_FORMAT_FEATURE_TRANSFER_SRC_BIT);
416 const auto colorProperties = vk::getPhysicalDeviceFormatProperties(vki, physicalDevice, kColorFormat);
417 if ((colorProperties.optimalTilingFeatures & kColorFeatures) != kColorFeatures)
418 TCU_THROW(NotSupportedError, "Required color image features not supported");
420 const auto dsProperties = vk::getPhysicalDeviceFormatProperties(vki, physicalDevice, kDepthStencilFormat);
421 if ((dsProperties.optimalTilingFeatures & kDSFeatures) != kDSFeatures)
422 TCU_THROW(NotSupportedError, "Required depth/stencil image features not supported");
425 void ExtendedDynamicStateTest::initPrograms (vk::SourceCollections& programCollection) const
427 std::ostringstream pushSource;
428 std::ostringstream vertSource;
429 std::ostringstream fragSource;
430 std::ostringstream geomSource;
433 << "layout(push_constant, std430) uniform PushConstantsBlock {\n"
434 << " vec4 triangleColor;\n"
435 << " float depthValue;\n"
436 << " int viewPortIndex;\n"
437 << " float scaleX;\n"
438 << " float scaleY;\n"
439 << " float offsetX;\n"
440 << " float offsetY;\n"
441 << "} pushConstants;\n"
443 const auto pushConstants = pushSource.str();
447 << "#extension GL_ARB_shader_viewport_layer_array : require\n"
449 << "layout(location=0) in vec2 position;\n"
450 << "out gl_PerVertex\n"
452 << " vec4 gl_Position;\n"
455 << " gl_Position = vec4(position.x * pushConstants.scaleX + pushConstants.offsetX, position.y * pushConstants.scaleY + pushConstants.offsetY, pushConstants.depthValue, 1.0);\n"
456 << " gl_ViewportIndex = pushConstants.viewPortIndex;\n"
463 << "layout(location=0) out vec4 color;\n"
465 << " color = pushConstants.triangleColor;\n"
469 if (m_testConfig.useGeometryShader)
471 const auto topologyClass = getTopologyClass(m_testConfig.topologyConfig.staticValue);
472 const std::string inputPrimitive = ((topologyClass == TopologyClass::LINE) ? "lines" : "triangles");
473 const deUint32 vertexCount = ((topologyClass == TopologyClass::LINE) ? 2u : 3u);
474 const std::string outputPrimitive = ((topologyClass == TopologyClass::LINE) ? "line_strip" : "triangle_strip");
478 << "layout (" << inputPrimitive << ") in;\n"
479 << "layout (" << outputPrimitive << ", max_vertices=" << vertexCount << ") out;\n"
480 << "in gl_PerVertex\n"
482 << " vec4 gl_Position;\n"
483 << "} gl_in[" << vertexCount << "];\n"
484 << "out gl_PerVertex\n"
486 << " vec4 gl_Position;\n"
491 for (deUint32 i = 0; i < vertexCount; ++i)
494 << " gl_Position = gl_in[" << i << "].gl_Position;\n"
495 << " EmitVertex();\n"
504 programCollection.glslSources.add("vert") << glu::VertexSource(vertSource.str());
505 programCollection.glslSources.add("frag") << glu::FragmentSource(fragSource.str());
506 if (m_testConfig.useGeometryShader)
507 programCollection.glslSources.add("geom") << glu::GeometrySource(geomSource.str());
510 TestInstance* ExtendedDynamicStateTest::createInstance (Context& context) const
512 return new ExtendedDynamicStateInstance(context, m_testConfig);
515 ExtendedDynamicStateInstance::ExtendedDynamicStateInstance(Context& context, const TestConfig& testConfig)
516 : vkt::TestInstance (context)
517 , m_testConfig (testConfig)
521 void logErrors(tcu::TestLog& log, const std::string& setName, const std::string& setDesc, const tcu::ConstPixelBufferAccess& result, const tcu::ConstPixelBufferAccess& errorMask)
523 log << tcu::TestLog::ImageSet(setName, setDesc)
524 << tcu::TestLog::Image(setName + "Result", "Result image", result)
525 << tcu::TestLog::Image(setName + "ErrorMask", "Error mask with errors marked in red", errorMask)
526 << tcu::TestLog::EndImageSet;
529 void copyAndFlush(const vk::DeviceInterface& vkd, vk::VkDevice device, vk::BufferWithMemory& buffer, const void* src, size_t size)
531 auto& alloc = buffer.getAllocation();
532 void* dst = alloc.getHostPtr();
534 deMemcpy(dst, src, size);
535 vk::flushAlloc(vkd, device, alloc);
538 // Sets values for dynamic states if needed according to the test configuration.
539 void setDynamicStates(const TestConfig& testConfig, const vk::DeviceInterface& vkd, vk::VkCommandBuffer cmdBuffer)
541 if (testConfig.cullModeConfig.dynamicValue)
542 vkd.cmdSetCullModeEXT(cmdBuffer, testConfig.cullModeConfig.dynamicValue.get());
544 if (testConfig.frontFaceConfig.dynamicValue)
545 vkd.cmdSetFrontFaceEXT(cmdBuffer, testConfig.frontFaceConfig.dynamicValue.get());
547 if (testConfig.topologyConfig.dynamicValue)
548 vkd.cmdSetPrimitiveTopologyEXT(cmdBuffer, testConfig.topologyConfig.dynamicValue.get());
550 if (testConfig.viewportConfig.dynamicValue)
552 const auto& viewports = testConfig.viewportConfig.dynamicValue.get();
553 vkd.cmdSetViewportWithCountEXT(cmdBuffer, static_cast<deUint32>(viewports.size()), viewports.data());
556 if (testConfig.scissorConfig.dynamicValue)
558 const auto& scissors = testConfig.scissorConfig.dynamicValue.get();
559 vkd.cmdSetScissorWithCountEXT(cmdBuffer, static_cast<deUint32>(scissors.size()), scissors.data());
562 if (testConfig.depthTestEnableConfig.dynamicValue)
563 vkd.cmdSetDepthTestEnableEXT(cmdBuffer, makeVkBool32(testConfig.depthTestEnableConfig.dynamicValue.get()));
565 if (testConfig.depthWriteEnableConfig.dynamicValue)
566 vkd.cmdSetDepthWriteEnableEXT(cmdBuffer, makeVkBool32(testConfig.depthWriteEnableConfig.dynamicValue.get()));
568 if (testConfig.depthCompareOpConfig.dynamicValue)
569 vkd.cmdSetDepthCompareOpEXT(cmdBuffer, testConfig.depthCompareOpConfig.dynamicValue.get());
571 if (testConfig.depthBoundsTestEnableConfig.dynamicValue)
572 vkd.cmdSetDepthBoundsTestEnableEXT(cmdBuffer, makeVkBool32(testConfig.depthBoundsTestEnableConfig.dynamicValue.get()));
574 if (testConfig.stencilTestEnableConfig.dynamicValue)
575 vkd.cmdSetStencilTestEnableEXT(cmdBuffer, makeVkBool32(testConfig.stencilTestEnableConfig.dynamicValue.get()));
577 if (testConfig.stencilOpConfig.dynamicValue)
579 for (const auto& params : testConfig.stencilOpConfig.dynamicValue.get())
580 vkd.cmdSetStencilOpEXT(cmdBuffer, params.faceMask, params.failOp, params.passOp, params.depthFailOp, params.compareOp);
584 // Get the proper viewport vector according to the test config.
585 const ViewportVec& getActiveViewportVec(const TestConfig& testConfig)
587 return (testConfig.viewportConfig.dynamicValue ? testConfig.viewportConfig.dynamicValue.get() : testConfig.viewportConfig.staticValue);
590 // Bind the appropriate vertex buffer with a dynamic stride if the test configuration needs a dynamic stride.
591 // Return true if the vertex buffer was bound.
592 bool maybeBindVertexBufferDynStride(const TestConfig& testConfig, const vk::DeviceInterface& vkd, vk::VkCommandBuffer cmdBuffer, size_t meshIdx, vk::VkBuffer vertBuffer, vk::VkBuffer rvertBuffer, vk::VkDeviceSize vertBufferSize, vk::VkDeviceSize vertBufferOffset)
594 if (testConfig.strideConfig.dynamicValue)
596 const auto& viewportVec = getActiveViewportVec(testConfig);
597 DE_UNREF(viewportVec); // For release builds.
599 // When dynamically setting the vertex buffer stride, we cannot bind the vertex buffer in advance for some sequence
600 // orderings when we have several viewports or meshes.
601 DE_ASSERT((viewportVec.size() == 1u && testConfig.meshParams.size() == 1u)
602 || testConfig.sequenceOrdering == SequenceOrdering::BEFORE_DRAW
603 || testConfig.sequenceOrdering == SequenceOrdering::AFTER_PIPELINES);
605 vkd.cmdBindVertexBuffers2EXT(cmdBuffer, 0u, 1u, (testConfig.meshParams[meshIdx].reversed ? &rvertBuffer : &vertBuffer), &vertBufferOffset, &vertBufferSize, &testConfig.strideConfig.dynamicValue.get());
612 tcu::TestStatus ExtendedDynamicStateInstance::iterate (void)
614 const auto& vkd = m_context.getDeviceInterface();
615 const auto device = m_context.getDevice();
616 auto& allocator = m_context.getDefaultAllocator();
617 const auto queue = m_context.getUniversalQueue();
618 const auto queueIndex = m_context.getUniversalQueueFamilyIndex();
620 const auto kFramebufferExtent = vk::makeExtent3D(kFramebufferWidth, kFramebufferHeight, 1u);
621 const vk::VkImageUsageFlags kColorUsage = (vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
622 const vk::VkImageUsageFlags kDSUsage = (vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
624 // Create color and depth/stencil images.
625 const vk::VkImageCreateInfo colorImageInfo =
627 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
628 nullptr, // const void* pNext;
629 0u, // VkImageCreateFlags flags;
630 vk::VK_IMAGE_TYPE_2D, // VkImageType imageType;
631 kColorFormat, // VkFormat format;
632 kFramebufferExtent, // VkExtent3D extent;
633 1u, // deUint32 mipLevels;
634 1u, // deUint32 arrayLayers;
635 vk::VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
636 vk::VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
637 kColorUsage, // VkImageUsageFlags usage;
638 vk::VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
639 1u, // deUint32 queueFamilyIndexCount;
640 &queueIndex, // const deUint32* pQueueFamilyIndices;
641 vk::VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
643 vk::ImageWithMemory colorImage(vkd, device, allocator, colorImageInfo, vk::MemoryRequirement::Any);
645 const vk::VkImageCreateInfo dsImageInfo =
647 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
648 nullptr, // const void* pNext;
649 0u, // VkImageCreateFlags flags;
650 vk::VK_IMAGE_TYPE_2D, // VkImageType imageType;
651 kDepthStencilFormat, // VkFormat format;
652 kFramebufferExtent, // VkExtent3D extent;
653 1u, // deUint32 mipLevels;
654 1u, // deUint32 arrayLayers;
655 vk::VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
656 vk::VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
657 kDSUsage, // VkImageUsageFlags usage;
658 vk::VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
659 1u, // deUint32 queueFamilyIndexCount;
660 &queueIndex, // const deUint32* pQueueFamilyIndices;
661 vk::VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
663 vk::ImageWithMemory dsImage(vkd, device, allocator, dsImageInfo, vk::MemoryRequirement::Any);
665 const auto colorSubresourceRange = vk::makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
666 const auto colorImageView = vk::makeImageView(vkd, device, colorImage.get(), vk::VK_IMAGE_VIEW_TYPE_2D, kColorFormat, colorSubresourceRange);
667 const auto dsSubresourceRange = vk::makeImageSubresourceRange((vk::VK_IMAGE_ASPECT_DEPTH_BIT | vk::VK_IMAGE_ASPECT_STENCIL_BIT), 0u, 1u, 0u, 1u);
668 const auto dsImageView = vk::makeImageView(vkd, device, dsImage.get(), vk::VK_IMAGE_VIEW_TYPE_2D, kDepthStencilFormat, dsSubresourceRange);
671 const auto topologyClass = getTopologyClass(m_testConfig.topologyConfig.staticValue);
672 std::vector<GeometryVertex> vertices;
674 if (topologyClass == TopologyClass::TRIANGLE)
676 // Full-scren triangle fan with 6 vertices.
689 vertices.push_back(GeometryVertex(tcu::Vec2( 0.0f, 1.0f)));
690 vertices.push_back(GeometryVertex(tcu::Vec2( 1.0f, 1.0f)));
691 vertices.push_back(GeometryVertex(tcu::Vec2( 1.0f, -1.0f)));
692 vertices.push_back(GeometryVertex(tcu::Vec2( 0.0f, -1.0f)));
693 vertices.push_back(GeometryVertex(tcu::Vec2(-1.0f, -1.0f)));
694 vertices.push_back(GeometryVertex(tcu::Vec2(-1.0f, 1.0f)));
696 else // TopologyClass::LINE
698 // 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.
699 const float lineHeight = 2.0f / static_cast<float>(kFramebufferHeight);
700 for (deUint32 rowIdx = 0; rowIdx < kFramebufferHeight; ++rowIdx)
702 // Offset of 0.5 pixels + one line per row from -1 to 1.
703 const float yCoord = (lineHeight / 2.0f) + lineHeight * static_cast<float>(rowIdx) - 1.0f;
704 vertices.push_back(GeometryVertex(tcu::Vec2(-1.0f, yCoord)));
705 vertices.push_back(GeometryVertex(tcu::Vec2(-0.5f, yCoord)));
706 vertices.push_back(GeometryVertex(tcu::Vec2( 0.5f, yCoord)));
707 vertices.push_back(GeometryVertex(tcu::Vec2( 1.0f, yCoord)));
711 // Reversed vertices, except for the first one (0, 5, 4, 3, 2, 1): clockwise mesh for triangles. Not to be used with lines.
712 std::vector<GeometryVertex> reversedVertices(1u, vertices[0]);
713 std::copy_n(vertices.rbegin(), vertices.size() - 1u, std::back_inserter(reversedVertices));
715 if (topologyClass == TopologyClass::LINE)
717 for (const auto& mesh : m_testConfig.meshParams)
719 DE_UNREF(mesh); // For release builds.
720 DE_ASSERT(!mesh.reversed);
724 const auto vertBufferSize = static_cast<vk::VkDeviceSize>(vertices.size() * sizeof(decltype(vertices)::value_type));
725 const auto vertBufferInfo = vk::makeBufferCreateInfo(vertBufferSize, vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
726 vk::BufferWithMemory vertBuffer (vkd, device, allocator, vertBufferInfo, vk::MemoryRequirement::HostVisible);
727 vk::BufferWithMemory rvertBuffer (vkd, device, allocator, vertBufferInfo, vk::MemoryRequirement::HostVisible);
729 // Copy data to vertex buffers and flush allocations.
730 copyAndFlush(vkd, device, vertBuffer, vertices.data(), static_cast<size_t>(vertBufferSize));
731 copyAndFlush(vkd, device, rvertBuffer, reversedVertices.data(), static_cast<size_t>(vertBufferSize));
732 const vk::VkDeviceSize vertBufferOffset = 0ull;
734 // Descriptor set layout.
735 vk::DescriptorSetLayoutBuilder layoutBuilder;
736 const auto descriptorSetLayout = layoutBuilder.build(vkd, device);
739 const vk::VkShaderStageFlags pushConstantStageFlags = (vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT);
740 const vk::VkPushConstantRange pushConstantRange =
742 pushConstantStageFlags, // VkShaderStageFlags stageFlags;
743 0u, // deUint32 offset;
744 static_cast<deUint32>(sizeof(PushConstants)), // deUint32 size;
747 const vk::VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo =
749 vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
750 nullptr, // const void* pNext;
751 0u, // VkPipelineLayoutCreateFlags flags;
752 1u, // deUint32 setLayoutCount;
753 &descriptorSetLayout.get(), // const VkDescriptorSetLayout* pSetLayouts;
754 1u, // deUint32 pushConstantRangeCount;
755 &pushConstantRange, // const VkPushConstantRange* pPushConstantRanges;
757 const auto pipelineLayout = vk::createPipelineLayout(vkd, device, &pipelineLayoutCreateInfo);
759 // Render pass with single subpass.
760 const vk::VkAttachmentReference colorAttachmentReference =
762 0u, // deUint32 attachment;
763 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout layout;
766 const vk::VkAttachmentReference dsAttachmentReference =
768 1u, // deUint32 attachment;
769 vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout layout;
772 const vk::VkSubpassDescription subpassDescription =
774 0u, // VkSubpassDescriptionFlags flags;
775 vk::VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
776 0u, // deUint32 inputAttachmentCount;
777 nullptr, // const VkAttachmentReference* pInputAttachments;
778 1u, // deUint32 colorAttachmentCount;
779 &colorAttachmentReference, // const VkAttachmentReference* pColorAttachments;
780 nullptr, // const VkAttachmentReference* pResolveAttachments;
781 &dsAttachmentReference, // const VkAttachmentReference* pDepthStencilAttachment;
782 0u, // deUint32 preserveAttachmentCount;
783 nullptr, // const deUint32* pPreserveAttachments;
786 std::vector<vk::VkAttachmentDescription> attachmentDescriptions;
788 attachmentDescriptions.push_back(vk::VkAttachmentDescription
790 0u, // VkAttachmentDescriptionFlags flags;
791 kColorFormat, // VkFormat format;
792 vk::VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
793 vk::VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
794 vk::VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
795 vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
796 vk::VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
797 vk::VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
798 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
801 attachmentDescriptions.push_back(vk::VkAttachmentDescription
803 0u, // VkAttachmentDescriptionFlags flags;
804 kDepthStencilFormat, // VkFormat format;
805 vk::VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
806 vk::VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
807 vk::VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
808 vk::VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp stencilLoadOp;
809 vk::VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp stencilStoreOp;
810 vk::VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
811 vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
814 const vk::VkRenderPassCreateInfo renderPassCreateInfo =
816 vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
817 nullptr, // const void* pNext;
818 0u, // VkRenderPassCreateFlags flags;
819 static_cast<deUint32>(attachmentDescriptions.size()), // deUint32 attachmentCount;
820 attachmentDescriptions.data(), // const VkAttachmentDescription* pAttachments;
821 1u, // deUint32 subpassCount;
822 &subpassDescription, // const VkSubpassDescription* pSubpasses;
823 0u, // deUint32 dependencyCount;
824 nullptr, // const VkSubpassDependency* pDependencies;
826 const auto renderPass = vk::createRenderPass(vkd, device, &renderPassCreateInfo);
829 std::vector<vk::VkImageView> attachments;
830 attachments.push_back(colorImageView.get());
831 attachments.push_back(dsImageView.get());
833 const vk::VkFramebufferCreateInfo framebufferCreateInfo =
835 vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
836 nullptr, // const void* pNext;
837 0u, // VkFramebufferCreateFlags flags;
838 renderPass.get(), // VkRenderPass renderPass;
839 static_cast<deUint32>(attachments.size()), // deUint32 attachmentCount;
840 attachments.data(), // const VkImageView* pAttachments;
841 kFramebufferWidth, // deUint32 width;
842 kFramebufferHeight, // deUint32 height;
843 1u, // deUint32 layers;
845 const auto framebuffer = vk::createFramebuffer(vkd, device, &framebufferCreateInfo);
848 const auto vertModule = vk::createShaderModule(vkd, device, m_context.getBinaryCollection().get("vert"), 0u);
849 const auto fragModule = vk::createShaderModule(vkd, device, m_context.getBinaryCollection().get("frag"), 0u);
850 vk::Move<vk::VkShaderModule> geomModule;
852 if (m_testConfig.useGeometryShader)
853 geomModule = vk::createShaderModule(vkd, device, m_context.getBinaryCollection().get("geom"), 0u);
856 std::vector<vk::VkPipelineShaderStageCreateInfo> shaderStages;
858 vk::VkPipelineShaderStageCreateInfo shaderStageCreateInfo =
860 vk::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
861 nullptr, // const void* pNext;
862 0u, // VkPipelineShaderStageCreateFlags flags;
863 vk::VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage;
864 vertModule.get(), // VkShaderModule module;
865 "main", // const char* pName;
866 nullptr, // const VkSpecializationInfo* pSpecializationInfo;
869 shaderStages.push_back(shaderStageCreateInfo);
870 shaderStageCreateInfo.stage = vk::VK_SHADER_STAGE_FRAGMENT_BIT;
871 shaderStageCreateInfo.module = fragModule.get();
872 shaderStages.push_back(shaderStageCreateInfo);
874 if (m_testConfig.useGeometryShader)
876 shaderStageCreateInfo.stage = vk::VK_SHADER_STAGE_GEOMETRY_BIT;
877 shaderStageCreateInfo.module = geomModule.get();
878 shaderStages.push_back(shaderStageCreateInfo);
882 const auto vertexBinding = vk::makeVertexInputBindingDescription(0u, static_cast<deUint32>(m_testConfig.strideConfig.staticValue), vk::VK_VERTEX_INPUT_RATE_VERTEX);
883 const auto vertexAttribute = vk::makeVertexInputAttributeDescription(0u, 0u, vk::VK_FORMAT_R32G32_SFLOAT, 0u);
885 const vk::VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo =
887 vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
888 nullptr, // const void* pNext;
889 0u, // VkPipelineVertexInputStateCreateFlags flags;
890 1u, // deUint32 vertexBindingDescriptionCount;
891 &vertexBinding, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
892 1u, // deUint32 vertexAttributeDescriptionCount;
893 &vertexAttribute, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
897 const vk::VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCreateInfo =
899 vk::VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
900 nullptr, // const void* pNext;
901 0u, // VkPipelineInputAssemblyStateCreateFlags flags;
902 m_testConfig.topologyConfig.staticValue, // VkPrimitiveTopology topology;
903 VK_FALSE, // VkBool32 primitiveRestartEnable;
907 if (m_testConfig.viewportConfig.dynamicValue)
908 DE_ASSERT(m_testConfig.viewportConfig.dynamicValue.get().size() > 0u);
910 DE_ASSERT(m_testConfig.viewportConfig.staticValue.size() > 0u);
912 if (m_testConfig.scissorConfig.dynamicValue)
913 DE_ASSERT(m_testConfig.scissorConfig.dynamicValue.get().size() > 0u);
915 DE_ASSERT(m_testConfig.scissorConfig.staticValue.size() > 0u);
917 const vk::VkPipelineViewportStateCreateInfo viewportStateCreateInfo =
919 vk::VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
920 nullptr, // const void* pNext;
921 0u, // VkPipelineViewportStateCreateFlags flags;
922 static_cast<deUint32>(m_testConfig.viewportConfig.staticValue.size()), // deUint32 viewportCount;
923 m_testConfig.viewportConfig.staticValue.data(), // const VkViewport* pViewports;
924 static_cast<deUint32>(m_testConfig.scissorConfig.staticValue.size()), // deUint32 scissorCount;
925 m_testConfig.scissorConfig.staticValue.data(), // const VkRect2D* pScissors;
928 // Rasterization state.
929 const vk::VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo =
931 vk::VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
932 nullptr, // const void* pNext;
933 0u, // VkPipelineRasterizationStateCreateFlags flags;
934 VK_FALSE, // VkBool32 depthClampEnable;
935 VK_FALSE, // VkBool32 rasterizerDiscardEnable;
936 vk::VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode;
937 m_testConfig.cullModeConfig.staticValue, // VkCullModeFlags cullMode;
938 m_testConfig.frontFaceConfig.staticValue, // VkFrontFace frontFace;
939 VK_FALSE, // VkBool32 depthBiasEnable;
940 0.0f, // float depthBiasConstantFactor;
941 0.0f, // float depthBiasClamp;
942 0.0f, // float depthBiasSlopeFactor;
943 1.0f, // float lineWidth;
946 // Multisample state.
947 const vk::VkPipelineMultisampleStateCreateInfo multisampleStateCreateInfo =
949 vk::VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
950 nullptr, // const void* pNext;
951 0u, // VkPipelineMultisampleStateCreateFlags flags;
952 vk::VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
953 VK_FALSE, // VkBool32 sampleShadingEnable;
954 0.0f, // float minSampleShading;
955 nullptr, // const VkSampleMask* pSampleMask;
956 VK_FALSE, // VkBool32 alphaToCoverageEnable;
957 VK_FALSE, // VkBool32 alphaToOneEnable;
960 // Depth/stencil state.
961 vk::VkStencilOpState staticFrontStencil;
962 vk::VkStencilOpState staticBackStencil;
963 bool staticFrontStencilSet = false;
964 bool staticBackStencilSet = false;
966 // Common setup for the front and back operations.
967 staticFrontStencil.compareMask = 0xFFu;
968 staticFrontStencil.writeMask = 0xFFu;
969 staticFrontStencil.reference = m_testConfig.referenceStencil;
970 staticBackStencil = staticFrontStencil;
972 for (const auto& op : m_testConfig.stencilOpConfig.staticValue)
974 if ((op.faceMask & vk::VK_STENCIL_FACE_FRONT_BIT) != 0u)
976 copy(staticFrontStencil, op);
977 staticFrontStencilSet = true;
979 if ((op.faceMask & vk::VK_STENCIL_FACE_BACK_BIT) != 0u)
981 copy(staticBackStencil, op);
982 staticBackStencilSet = true;
986 // Default values for the static part.
987 if (!staticFrontStencilSet)
988 copy(staticFrontStencil, kDefaultStencilOpParams);
989 if (!staticBackStencilSet)
990 copy(staticBackStencil, kDefaultStencilOpParams);
992 const vk::VkPipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo =
994 vk::VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
995 nullptr, // const void* pNext;
996 0u, // VkPipelineDepthStencilStateCreateFlags flags;
997 makeVkBool32(m_testConfig.depthTestEnableConfig.staticValue), // VkBool32 depthTestEnable;
998 makeVkBool32(m_testConfig.depthWriteEnableConfig.staticValue), // VkBool32 depthWriteEnable;
999 m_testConfig.depthCompareOpConfig.staticValue, // VkCompareOp depthCompareOp;
1000 makeVkBool32(m_testConfig.depthBoundsTestEnableConfig.staticValue), // VkBool32 depthBoundsTestEnable;
1001 makeVkBool32(m_testConfig.stencilTestEnableConfig.staticValue), // VkBool32 stencilTestEnable;
1002 staticFrontStencil, // VkStencilOpState front;
1003 staticBackStencil, // VkStencilOpState back;
1004 m_testConfig.minDepthBounds, // float minDepthBounds;
1005 m_testConfig.maxDepthBounds, // float maxDepthBounds;
1008 // Dynamic state. Here we will set all states which have a dynamic value.
1009 std::vector<vk::VkDynamicState> dynamicStates;
1011 if (m_testConfig.cullModeConfig.dynamicValue) dynamicStates.push_back(vk::VK_DYNAMIC_STATE_CULL_MODE_EXT);
1012 if (m_testConfig.frontFaceConfig.dynamicValue) dynamicStates.push_back(vk::VK_DYNAMIC_STATE_FRONT_FACE_EXT);
1013 if (m_testConfig.topologyConfig.dynamicValue) dynamicStates.push_back(vk::VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT);
1014 if (m_testConfig.viewportConfig.dynamicValue) dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT_EXT);
1015 if (m_testConfig.scissorConfig.dynamicValue) dynamicStates.push_back(vk::VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT_EXT);
1016 if (m_testConfig.strideConfig.dynamicValue) dynamicStates.push_back(vk::VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT);
1017 if (m_testConfig.depthTestEnableConfig.dynamicValue) dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE_EXT);
1018 if (m_testConfig.depthWriteEnableConfig.dynamicValue) dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE_EXT);
1019 if (m_testConfig.depthCompareOpConfig.dynamicValue) dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_COMPARE_OP_EXT);
1020 if (m_testConfig.depthBoundsTestEnableConfig.dynamicValue) dynamicStates.push_back(vk::VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE_EXT);
1021 if (m_testConfig.stencilTestEnableConfig.dynamicValue) dynamicStates.push_back(vk::VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE_EXT);
1022 if (m_testConfig.stencilOpConfig.dynamicValue) dynamicStates.push_back(vk::VK_DYNAMIC_STATE_STENCIL_OP_EXT);
1024 const vk::VkPipelineDynamicStateCreateInfo dynamicStateCreateInfo =
1026 vk::VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType;
1027 nullptr, // const void* pNext;
1028 0u, // VkPipelineDynamicStateCreateFlags flags;
1029 static_cast<deUint32>(dynamicStates.size()), // deUint32 dynamicStateCount;
1030 dynamicStates.data(), // const VkDynamicState* pDynamicStates;
1033 const vk::VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
1035 VK_FALSE, // VkBool32 blendEnable
1036 vk::VK_BLEND_FACTOR_ZERO, // VkBlendFactor srcColorBlendFactor
1037 vk::VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor
1038 vk::VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp
1039 vk::VK_BLEND_FACTOR_ZERO, // VkBlendFactor srcAlphaBlendFactor
1040 vk::VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor
1041 vk::VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp
1042 vk::VK_COLOR_COMPONENT_R_BIT // VkColorComponentFlags colorWriteMask
1043 | vk::VK_COLOR_COMPONENT_G_BIT
1044 | vk::VK_COLOR_COMPONENT_B_BIT
1045 | vk::VK_COLOR_COMPONENT_A_BIT
1048 const vk::VkPipelineColorBlendStateCreateInfo colorBlendStateCreateInfo =
1050 vk::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType
1051 nullptr, // const void* pNext
1052 0u, // VkPipelineColorBlendStateCreateFlags flags
1053 VK_FALSE, // VkBool32 logicOpEnable
1054 vk::VK_LOGIC_OP_CLEAR, // VkLogicOp logicOp
1055 1u, // deUint32 attachmentCount
1056 &colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments
1057 { 0.0f, 0.0f, 0.0f, 0.0f } // float blendConstants[4]
1060 const vk::VkGraphicsPipelineCreateInfo graphicsPipelineCreateInfo =
1062 vk::VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
1063 nullptr, // const void* pNext;
1064 0u, // VkPipelineCreateFlags flags;
1065 static_cast<deUint32>(shaderStages.size()), // deUint32 stageCount;
1066 shaderStages.data(), // const VkPipelineShaderStageCreateInfo* pStages;
1067 &vertexInputStateCreateInfo, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
1068 &inputAssemblyStateCreateInfo, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
1069 nullptr, // const VkPipelineTessellationStateCreateInfo* pTessellationState;
1070 &viewportStateCreateInfo, // const VkPipelineViewportStateCreateInfo* pViewportState;
1071 &rasterizationStateCreateInfo, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState;
1072 &multisampleStateCreateInfo, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
1073 &depthStencilStateCreateInfo, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
1074 &colorBlendStateCreateInfo, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
1075 &dynamicStateCreateInfo, // const VkPipelineDynamicStateCreateInfo* pDynamicState;
1076 pipelineLayout.get(), // VkPipelineLayout layout;
1077 renderPass.get(), // VkRenderPass renderPass;
1078 0u, // deUint32 subpass;
1079 DE_NULL, // VkPipeline basePipelineHandle;
1080 0, // deInt32 basePipelineIndex;
1082 const auto graphicsPipeline = vk::createGraphicsPipeline(vkd, device, DE_NULL, &graphicsPipelineCreateInfo);
1084 const bool useStaticPipeline = (m_testConfig.sequenceOrdering == SequenceOrdering::BETWEEN_PIPELINES || m_testConfig.sequenceOrdering == SequenceOrdering::AFTER_PIPELINES);
1086 vk::Move<vk::VkPipeline> staticPipeline;
1087 if (useStaticPipeline)
1089 auto staticPipelineCreateInfo = graphicsPipelineCreateInfo;
1090 staticPipelineCreateInfo.pDynamicState = nullptr;
1091 staticPipeline = vk::createGraphicsPipeline(vkd, device, DE_NULL, &staticPipelineCreateInfo);
1095 const auto cmdPool = vk::makeCommandPool(vkd, device, queueIndex);
1096 const auto cmdBufferPtr = vk::allocateCommandBuffer(vkd , device, cmdPool.get(), vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1097 const auto cmdBuffer = cmdBufferPtr.get();
1100 std::vector<vk::VkClearValue> clearValues;
1101 clearValues.push_back(vk::makeClearValueColor(m_testConfig.clearColorValue));
1102 clearValues.push_back(vk::makeClearValueDepthStencil(m_testConfig.clearDepthValue, m_testConfig.clearStencilValue));
1104 // Track in-advance vertex buffer binding.
1105 bool boundInAdvance = false;
1107 // Record command buffer.
1108 vk::beginCommandBuffer(vkd, cmdBuffer);
1110 // Maybe set extended dynamic state here.
1111 if (m_testConfig.sequenceOrdering == SequenceOrdering::CMD_BUFFER_START)
1113 setDynamicStates(m_testConfig, vkd, cmdBuffer);
1114 boundInAdvance = maybeBindVertexBufferDynStride(m_testConfig, vkd, cmdBuffer, 0u, vertBuffer.get(), rvertBuffer.get(), vertBufferSize, vertBufferOffset);
1117 // Begin render pass.
1118 vk::beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffer.get(), vk::makeRect2D(kFramebufferWidth, kFramebufferHeight), static_cast<deUint32>(clearValues.size()), clearValues.data());
1120 // Bind a static pipeline first if needed.
1121 if (useStaticPipeline)
1122 vkd.cmdBindPipeline(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, staticPipeline.get());
1124 // Maybe set extended dynamic state here.
1125 if (m_testConfig.sequenceOrdering == SequenceOrdering::BETWEEN_PIPELINES)
1127 setDynamicStates(m_testConfig, vkd, cmdBuffer);
1128 boundInAdvance = maybeBindVertexBufferDynStride(m_testConfig, vkd, cmdBuffer, 0u, vertBuffer.get(), rvertBuffer.get(), vertBufferSize, vertBufferOffset);
1131 // Bind dynamic pipeline.
1132 vkd.cmdBindPipeline(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline.get());
1134 const auto& viewportVec = getActiveViewportVec(m_testConfig);
1135 for (size_t viewportIdx = 0u; viewportIdx < viewportVec.size(); ++viewportIdx)
1137 for (size_t meshIdx = 0u; meshIdx < m_testConfig.meshParams.size(); ++meshIdx)
1140 PushConstants pushConstants =
1142 m_testConfig.meshParams[meshIdx].color, // tcu::Vec4 triangleColor;
1143 m_testConfig.meshParams[meshIdx].depth, // float meshDepth;
1144 static_cast<deInt32>(viewportIdx), // deInt32 viewPortIndex;
1145 m_testConfig.meshParams[meshIdx].scaleX, // float scaleX;
1146 m_testConfig.meshParams[meshIdx].scaleY, // float scaleY;
1147 m_testConfig.meshParams[meshIdx].offsetX, // float offsetX;
1148 m_testConfig.meshParams[meshIdx].offsetY, // float offsetY;
1150 vkd.cmdPushConstants(cmdBuffer, pipelineLayout.get(), pushConstantStageFlags, 0u, static_cast<deUint32>(sizeof(pushConstants)), &pushConstants);
1152 // Track vertex bounding state for this mesh.
1153 bool boundBeforeDraw = false;
1155 // Maybe set extended dynamic state here.
1156 if (m_testConfig.sequenceOrdering == SequenceOrdering::BEFORE_DRAW || m_testConfig.sequenceOrdering == SequenceOrdering::AFTER_PIPELINES)
1158 setDynamicStates(m_testConfig, vkd, cmdBuffer);
1159 boundBeforeDraw = maybeBindVertexBufferDynStride(m_testConfig, vkd, cmdBuffer, meshIdx, vertBuffer.get(), rvertBuffer.get(), vertBufferSize, vertBufferOffset);
1162 // Bind vertex buffer with static stride if needed and draw.
1163 if (!(boundInAdvance || boundBeforeDraw))
1164 vkd.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, (m_testConfig.meshParams[meshIdx].reversed ? &rvertBuffer.get() : &vertBuffer.get()), &vertBufferOffset);
1167 vkd.cmdDraw(cmdBuffer, static_cast<deUint32>(vertices.size()), 1u, 0u, 0u);
1171 vk::endRenderPass(vkd, cmdBuffer);
1172 vk::endCommandBuffer(vkd, cmdBuffer);
1175 vk::submitCommandsAndWait(vkd, device, queue, cmdBuffer);
1177 // Read result image aspects.
1178 const tcu::UVec2 renderSize (kFramebufferWidth, kFramebufferHeight);
1179 const auto colorBuffer = readColorAttachment(vkd, device, queue, queueIndex, allocator, colorImage.get(), kColorFormat, renderSize);
1180 const auto depthBuffer = readDepthAttachment(vkd, device, queue, queueIndex, allocator, dsImage.get(), kDepthStencilFormat, renderSize);
1181 const auto stencilBuffer = readStencilAttachment(vkd, device, queue, queueIndex, allocator, dsImage.get(), kDepthStencilFormat, renderSize, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
1182 const auto colorAccess = colorBuffer->getAccess();
1183 const auto depthAccess = depthBuffer->getAccess();
1184 const auto stencilAccess = stencilBuffer->getAccess();
1186 const int kWidth = static_cast<int>(kFramebufferWidth);
1187 const int kHeight = static_cast<int>(kFramebufferHeight);
1189 const tcu::TextureFormat errorFormat (tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8);
1190 tcu::TextureLevel colorError (errorFormat, kWidth, kHeight);
1191 tcu::TextureLevel depthError (errorFormat, kWidth, kHeight);
1192 tcu::TextureLevel stencilError (errorFormat, kWidth, kHeight);
1193 const auto colorErrorAccess = colorError.getAccess();
1194 const auto depthErrorAccess = depthError.getAccess();
1195 const auto stencilErrorAccess = stencilError.getAccess();
1196 const tcu::Vec4 kGood (0.0f, 1.0f, 0.0f, 1.0f);
1197 const tcu::Vec4 kBad (1.0f, 0.0f, 0.0f, 1.0f);
1199 // Check expected values.
1200 bool colorMatch = true;
1201 bool depthMatch = true;
1202 bool stencilMatch = true;
1205 for (int x = 0; x < kWidth; ++x)
1206 for (int y = 0; y < kHeight; ++y)
1208 const auto colorPixel = colorAccess.getPixel(x, y);
1209 match = tcu::boolAll(tcu::lessThan(tcu::absDiff(colorPixel, m_testConfig.expectedColor), kColorThreshold));
1210 colorErrorAccess.setPixel((match ? kGood : kBad), x, y);
1214 const auto depthPixel = depthAccess.getPixDepth(x, y);
1215 match = (depthPixel == m_testConfig.expectedDepth);
1216 depthErrorAccess.setPixel((match ? kGood : kBad), x, y);
1220 const auto stencilPixel = static_cast<deUint32>(stencilAccess.getPixStencil(x, y));
1221 match = (stencilPixel == m_testConfig.expectedStencil);
1222 stencilErrorAccess.setPixel((match ? kGood : kBad), x, y);
1224 stencilMatch = false;
1227 if (!(colorMatch && depthMatch && stencilMatch))
1229 auto& log = m_context.getTestContext().getLog();
1232 logErrors(log, "Color", "Result color image and error mask", colorAccess, colorErrorAccess);
1235 logErrors(log, "Depth", "Result depth image and error mask", depthAccess, depthErrorAccess);
1238 logErrors(log, "Stencil", "Result stencil image and error mask", stencilAccess, stencilErrorAccess);
1240 return tcu::TestStatus::fail("Incorrect value found in attachments; please check logged images");
1243 return tcu::TestStatus::pass("Pass");
1246 bool stencilPasses(vk::VkCompareOp op, deUint8 storedValue, deUint8 referenceValue)
1250 case vk::VK_COMPARE_OP_NEVER: return false;
1251 case vk::VK_COMPARE_OP_LESS: return (referenceValue < storedValue);
1252 case vk::VK_COMPARE_OP_EQUAL: return (referenceValue == storedValue);
1253 case vk::VK_COMPARE_OP_LESS_OR_EQUAL: return (referenceValue <= storedValue);
1254 case vk::VK_COMPARE_OP_GREATER: return (referenceValue > storedValue);
1255 case vk::VK_COMPARE_OP_GREATER_OR_EQUAL: return (referenceValue >= storedValue);
1256 case vk::VK_COMPARE_OP_ALWAYS: return true;
1257 default: DE_ASSERT(false); return false;
1260 return false; // Unreachable.
1263 deUint8 stencilResult(vk::VkStencilOp op, deUint8 storedValue, deUint8 referenceValue, deUint8 min, deUint8 max)
1265 deUint8 result = storedValue;
1269 case vk::VK_STENCIL_OP_KEEP: break;
1270 case vk::VK_STENCIL_OP_ZERO: result = 0; break;
1271 case vk::VK_STENCIL_OP_REPLACE: result = referenceValue; break;
1272 case vk::VK_STENCIL_OP_INCREMENT_AND_CLAMP: result = ((result == max) ? result : static_cast<deUint8>(result + 1)); break;
1273 case vk::VK_STENCIL_OP_DECREMENT_AND_CLAMP: result = ((result == min) ? result : static_cast<deUint8>(result - 1)); break;
1274 case vk::VK_STENCIL_OP_INVERT: result = static_cast<deUint8>(~result); break;
1275 case vk::VK_STENCIL_OP_INCREMENT_AND_WRAP: result = ((result == max) ? min : static_cast<deUint8>(result + 1)); break;
1276 case vk::VK_STENCIL_OP_DECREMENT_AND_WRAP: result = ((result == min) ? max : static_cast<deUint8>(result - 1)); break;
1277 default: DE_ASSERT(false); break;
1283 } // anonymous namespace
1285 tcu::TestCaseGroup* createExtendedDynamicStateTests (tcu::TestContext& testCtx)
1287 de::MovePtr<tcu::TestCaseGroup> extendedDynamicStateGroup(new tcu::TestCaseGroup(testCtx, "extended_dynamic_state", "Tests for VK_EXT_extended_dynamic_state"));
1289 // Auxiliar constants.
1290 const deUint32 kHalfWidthU = kFramebufferWidth/2u;
1291 const deInt32 kHalfWidthI = static_cast<deInt32>(kHalfWidthU);
1292 const float kHalfWidthF = static_cast<float>(kHalfWidthU);
1293 const float kHeightF = static_cast<float>(kFramebufferHeight);
1297 SequenceOrdering ordering;
1300 } kOrderingCases[] =
1302 { SequenceOrdering::CMD_BUFFER_START, "cmd_buffer_start", "Dynamic state set after command buffer start" },
1303 { SequenceOrdering::BEFORE_DRAW, "before_draw", "Dynamic state set just before drawing" },
1304 { 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" },
1305 { SequenceOrdering::AFTER_PIPELINES, "after_pipelines", "Dynamic state set after both a static-state pipeline and a second dynamic-state pipeline have been bound" },
1308 for (int orderingIdx = 0; orderingIdx < DE_LENGTH_OF_ARRAY(kOrderingCases); ++orderingIdx)
1310 const auto& kOrderingCase = kOrderingCases[orderingIdx];
1311 const auto& kOrdering = kOrderingCase.ordering;
1313 de::MovePtr<tcu::TestCaseGroup> orderingGroup(new tcu::TestCaseGroup(testCtx, kOrderingCase.name.c_str(), kOrderingCase.desc.c_str()));
1317 TestConfig config(kOrdering);
1318 config.cullModeConfig.staticValue = vk::VK_CULL_MODE_FRONT_BIT;
1319 config.cullModeConfig.dynamicValue = tcu::just<vk::VkCullModeFlags>(vk::VK_CULL_MODE_NONE);
1320 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "cull_none", "Dynamically set cull mode to none", config));
1323 TestConfig config(kOrdering);
1324 config.cullModeConfig.staticValue = vk::VK_CULL_MODE_FRONT_AND_BACK;
1325 config.cullModeConfig.dynamicValue = tcu::just<vk::VkCullModeFlags>(vk::VK_CULL_MODE_BACK_BIT);
1326 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "cull_back", "Dynamically set cull mode to back", config));
1329 TestConfig config(kOrdering);
1330 // Make triangles look back.
1331 config.meshParams[0].reversed = true;
1332 config.cullModeConfig.staticValue = vk::VK_CULL_MODE_BACK_BIT;
1333 config.cullModeConfig.dynamicValue = tcu::just<vk::VkCullModeFlags>(vk::VK_CULL_MODE_FRONT_BIT);
1334 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "cull_front", "Dynamically set cull mode to front", config));
1337 TestConfig config(kOrdering);
1338 config.cullModeConfig.staticValue = vk::VK_CULL_MODE_NONE;
1339 config.cullModeConfig.dynamicValue = tcu::just<vk::VkCullModeFlags>(vk::VK_CULL_MODE_FRONT_AND_BACK);
1340 config.expectedColor = kDefaultClearColor;
1341 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "cull_front_and_back", "Dynamically set cull mode to front and back", config));
1346 TestConfig config(kOrdering);
1347 config.cullModeConfig.staticValue = vk::VK_CULL_MODE_BACK_BIT;
1348 config.frontFaceConfig.staticValue = vk::VK_FRONT_FACE_CLOCKWISE;
1349 config.frontFaceConfig.dynamicValue = tcu::just<vk::VkFrontFace>(vk::VK_FRONT_FACE_COUNTER_CLOCKWISE);
1350 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "front_face_cw", "Dynamically set front face to clockwise", config));
1353 TestConfig config(kOrdering);
1354 // Pass triangles in clockwise order.
1355 config.meshParams[0].reversed = true;
1356 config.cullModeConfig.staticValue = vk::VK_CULL_MODE_BACK_BIT;
1357 config.frontFaceConfig.staticValue = vk::VK_FRONT_FACE_COUNTER_CLOCKWISE;
1358 config.frontFaceConfig.dynamicValue = tcu::just<vk::VkFrontFace>(vk::VK_FRONT_FACE_CLOCKWISE);
1359 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "front_face_ccw", "Dynamically set front face to counter-clockwise", config));
1362 TestConfig config(kOrdering);
1363 config.cullModeConfig.staticValue = vk::VK_CULL_MODE_BACK_BIT;
1364 config.frontFaceConfig.staticValue = vk::VK_FRONT_FACE_COUNTER_CLOCKWISE;
1365 config.frontFaceConfig.dynamicValue = tcu::just<vk::VkFrontFace>(vk::VK_FRONT_FACE_CLOCKWISE);
1366 config.expectedColor = kDefaultClearColor;
1367 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "front_face_cw_reversed", "Dynamically set front face to clockwise with a counter-clockwise mesh", config));
1370 TestConfig config(kOrdering);
1371 // Pass triangles in clockwise order.
1372 config.meshParams[0].reversed = true;
1373 config.cullModeConfig.staticValue = vk::VK_CULL_MODE_BACK_BIT;
1374 config.frontFaceConfig.staticValue = vk::VK_FRONT_FACE_CLOCKWISE;
1375 config.frontFaceConfig.dynamicValue = tcu::just<vk::VkFrontFace>(vk::VK_FRONT_FACE_COUNTER_CLOCKWISE);
1376 config.expectedColor = kDefaultClearColor;
1377 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "front_face_ccw_reversed", "Dynamically set front face to counter-clockwise with a clockwise mesh", config));
1380 // Dynamic topology.
1382 TestConfig baseConfig(kOrdering);
1384 for (int i = 0; i < 2; ++i)
1386 const bool useGeometryShader = (i > 0);
1390 vk::VkPrimitiveTopology staticVal;
1391 vk::VkPrimitiveTopology dynamicVal;
1392 } kTopologyCases[] =
1394 { vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN },
1395 { vk::VK_PRIMITIVE_TOPOLOGY_LINE_LIST, vk::VK_PRIMITIVE_TOPOLOGY_LINE_STRIP },
1398 for (int topoCaseIdx = 0; topoCaseIdx < DE_LENGTH_OF_ARRAY(kTopologyCases); ++topoCaseIdx)
1400 TestConfig config(baseConfig);
1401 config.useGeometryShader = useGeometryShader;
1402 config.topologyConfig.staticValue = kTopologyCases[topoCaseIdx].staticVal;
1403 config.topologyConfig.dynamicValue = tcu::just<vk::VkPrimitiveTopology>(kTopologyCases[topoCaseIdx].dynamicVal);
1405 const std::string className = topologyClassName(getTopologyClass(config.topologyConfig.staticValue));
1406 const std::string name = "topology_" + className + (useGeometryShader ? "_geom" : "");
1407 const std::string desc = "Dynamically switch primitive topologies from the " + className + " class" + (useGeometryShader ? " and use a geometry shader" : "");
1408 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, name, desc, config));
1415 TestConfig config(kOrdering);
1416 // 2 scissors, bad static single viewport.
1417 config.scissorConfig.staticValue = ScissorVec{vk::makeRect2D(0, 0, kHalfWidthU, kFramebufferHeight), vk::makeRect2D(kHalfWidthI, 0, kHalfWidthU, kFramebufferHeight)};
1418 config.viewportConfig.staticValue = ViewportVec(1u, vk::makeViewport(kHalfWidthU, kFramebufferHeight));
1419 config.viewportConfig.dynamicValue = ViewportVec{
1420 vk::makeViewport(0.0f, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f),
1421 vk::makeViewport(kHalfWidthF, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f),
1423 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "2_viewports", "Dynamically set 2 viewports", config));
1426 TestConfig config(kOrdering);
1427 // Bad static reduced viewport.
1428 config.viewportConfig.staticValue = ViewportVec(1u, vk::makeViewport(kHalfWidthU, kFramebufferHeight));
1429 config.viewportConfig.staticValue = ViewportVec(1u, vk::makeViewport(kFramebufferWidth, kFramebufferHeight));
1430 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "1_full_viewport", "Dynamically set viewport to cover full framebuffer", config));
1433 TestConfig config(kOrdering);
1434 // 2 scissors (left half, right half), 2 reversed static viewports that need fixing (right, left).
1435 config.scissorConfig.staticValue = ScissorVec{vk::makeRect2D(0, 0, kHalfWidthU, kFramebufferHeight), vk::makeRect2D(kHalfWidthI, 0, kHalfWidthU, kFramebufferHeight)};
1436 config.viewportConfig.staticValue = ViewportVec{
1437 vk::makeViewport(kHalfWidthF, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f), // Right.
1438 vk::makeViewport(0.0f, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f), // Left.
1440 config.viewportConfig.dynamicValue = ViewportVec{config.viewportConfig.staticValue.back(), config.viewportConfig.staticValue.front()};
1441 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "2_viewports_switch", "Dynamically switch the order with 2 viewports", config));
1444 TestConfig config(kOrdering);
1445 // 2 scissors, reversed dynamic viewports that should result in no drawing taking place.
1446 config.scissorConfig.staticValue = ScissorVec{vk::makeRect2D(0, 0, kHalfWidthU, kFramebufferHeight), vk::makeRect2D(kHalfWidthI, 0, kHalfWidthU, kFramebufferHeight)};
1447 config.viewportConfig.staticValue = ViewportVec{
1448 vk::makeViewport(0.0f, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f), // Left.
1449 vk::makeViewport(kHalfWidthF, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f), // Right.
1451 config.viewportConfig.dynamicValue = ViewportVec{config.viewportConfig.staticValue.back(), config.viewportConfig.staticValue.front()};
1452 config.expectedColor = kDefaultClearColor;
1453 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "2_viewports_switch_clean", "Dynamically switch the order with 2 viewports resulting in clean image", config));
1458 TestConfig config(kOrdering);
1459 // 2 viewports, bad static single scissor.
1460 config.viewportConfig.staticValue = ViewportVec{
1461 vk::makeViewport(0.0f, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f),
1462 vk::makeViewport(kHalfWidthF, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f),
1464 config.scissorConfig.staticValue = ScissorVec(1u, vk::makeRect2D(kHalfWidthI, 0, kHalfWidthU, kFramebufferHeight));
1465 config.scissorConfig.dynamicValue = ScissorVec{
1466 vk::makeRect2D(kHalfWidthU, kFramebufferHeight),
1467 vk::makeRect2D(kHalfWidthI, 0, kHalfWidthU, kFramebufferHeight),
1469 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "2_scissors", "Dynamically set 2 scissors", config));
1472 TestConfig config(kOrdering);
1473 // 1 viewport, bad static single scissor.
1474 config.scissorConfig.staticValue = ScissorVec(1u, vk::makeRect2D(kHalfWidthI, 0, kHalfWidthU, kFramebufferHeight));
1475 config.scissorConfig.dynamicValue = ScissorVec(1u, vk::makeRect2D(kFramebufferWidth, kFramebufferHeight));
1476 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "1_full_scissor", "Dynamically set scissor to cover full framebuffer", config));
1479 TestConfig config(kOrdering);
1480 // 2 viewports, 2 reversed scissors that need fixing.
1481 config.viewportConfig.staticValue = ViewportVec{
1482 vk::makeViewport(0.0f, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f),
1483 vk::makeViewport(kHalfWidthF, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f),
1485 config.scissorConfig.staticValue = ScissorVec{
1486 vk::makeRect2D(kHalfWidthI, 0, kHalfWidthU, kFramebufferHeight),
1487 vk::makeRect2D(kHalfWidthU, kFramebufferHeight),
1489 config.scissorConfig.dynamicValue = ScissorVec{config.scissorConfig.staticValue.back(), config.scissorConfig.staticValue.front()};
1490 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "2_scissors_switch", "Dynamically switch the order with 2 scissors", config));
1493 TestConfig config(kOrdering);
1494 // 2 viewports, 2 scissors switched to prevent drawing.
1495 config.viewportConfig.staticValue = ViewportVec{
1496 vk::makeViewport(0.0f, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f),
1497 vk::makeViewport(kHalfWidthF, 0.0f, kHalfWidthF, kHeightF, 0.0f, 1.0f),
1499 config.scissorConfig.staticValue = ScissorVec{
1500 vk::makeRect2D(kHalfWidthU, kFramebufferHeight),
1501 vk::makeRect2D(kHalfWidthI, 0, kHalfWidthU, kFramebufferHeight),
1503 config.scissorConfig.dynamicValue = ScissorVec{config.scissorConfig.staticValue.back(), config.scissorConfig.staticValue.front()};
1504 config.expectedColor = kDefaultClearColor;
1505 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "2_scissors_switch_clean", "Dynamically switch the order with 2 scissors to avoid drawing", config));
1510 TestConfig config(kOrdering);
1511 config.strideConfig.staticValue = kCoordsSize;
1512 config.strideConfig.dynamicValue = kVertexStride;
1513 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "stride", "Dynamically set stride", config));
1516 // Depth test enable.
1518 TestConfig config(kOrdering);
1519 config.depthTestEnableConfig.staticValue = false;
1520 config.depthTestEnableConfig.dynamicValue = tcu::just(true);
1521 // By default, the depth test never passes when enabled.
1522 config.expectedColor = kDefaultClearColor;
1523 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_test_enable", "Dynamically enable depth test", config));
1526 TestConfig config(kOrdering);
1527 config.depthTestEnableConfig.staticValue = true;
1528 config.depthTestEnableConfig.dynamicValue = tcu::just(false);
1529 config.expectedColor = kDefaultTriangleColor;
1530 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_test_disable", "Dynamically disable depth test", config));
1533 // Depth write enable.
1535 TestConfig config(kOrdering);
1537 // Enable depth test and set values so it passes.
1538 config.depthTestEnableConfig.staticValue = true;
1539 config.depthCompareOpConfig.staticValue = vk::VK_COMPARE_OP_LESS;
1540 config.clearDepthValue = 0.5f;
1541 config.meshParams[0].depth = 0.25f;
1543 // Enable writes and expect the mesh value.
1544 config.depthWriteEnableConfig.staticValue = false;
1545 config.depthWriteEnableConfig.dynamicValue = tcu::just(true);
1546 config.expectedDepth = 0.25f;
1548 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_write_enable", "Dynamically enable writes to the depth buffer", config));
1551 TestConfig config(kOrdering);
1553 // Enable depth test and set values so it passes.
1554 config.depthTestEnableConfig.staticValue = true;
1555 config.depthCompareOpConfig.staticValue = vk::VK_COMPARE_OP_LESS;
1556 config.clearDepthValue = 0.5f;
1557 config.meshParams[0].depth = 0.25f;
1559 // But disable writing dynamically and expect the clear value.
1560 config.depthWriteEnableConfig.staticValue = true;
1561 config.depthWriteEnableConfig.dynamicValue = tcu::just(false);
1562 config.expectedDepth = 0.5f;
1564 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_write_disable", "Dynamically disable writes to the depth buffer", config));
1567 // Depth compare op.
1569 TestConfig baseConfig(kOrdering);
1570 const tcu::Vec4 kAlternativeColor (0.0f, 0.0f, 0.5f, 1.0f);
1571 baseConfig.depthTestEnableConfig.staticValue = true;
1572 baseConfig.depthWriteEnableConfig.staticValue = true;
1573 baseConfig.depthCompareOpConfig.staticValue = vk::VK_COMPARE_OP_NEVER;
1574 baseConfig.clearDepthValue = 0.5f;
1577 TestConfig config = baseConfig;
1578 config.depthCompareOpConfig.staticValue = vk::VK_COMPARE_OP_ALWAYS;
1579 config.depthCompareOpConfig.dynamicValue = vk::VK_COMPARE_OP_NEVER;
1580 config.meshParams[0].depth = 0.25f;
1581 config.expectedDepth = 0.5f;
1582 config.expectedColor = kDefaultClearColor;
1583 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_never", "Dynamically set the depth compare operator to NEVER", config));
1586 TestConfig config = baseConfig;
1587 config.depthCompareOpConfig.dynamicValue = vk::VK_COMPARE_OP_LESS;
1588 config.meshParams[0].depth = 0.25f;
1589 config.expectedDepth = 0.25f;
1590 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_less", "Dynamically set the depth compare operator to LESS", config));
1593 TestConfig config = baseConfig;
1594 config.depthCompareOpConfig.dynamicValue = vk::VK_COMPARE_OP_GREATER;
1595 config.meshParams[0].depth = 0.75f;
1596 config.expectedDepth = 0.75f;
1597 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_greater", "Dynamically set the depth compare operator to GREATER", config));
1600 TestConfig config = baseConfig;
1601 config.depthCompareOpConfig.dynamicValue = vk::VK_COMPARE_OP_EQUAL;
1602 config.meshParams[0].depth = 0.5f;
1603 config.meshParams[0].color = kAlternativeColor;
1604 // Draw another mesh in front to verify it does not pass the equality test.
1605 config.meshParams.push_back(MeshParams(kDefaultTriangleColor, 0.25f));
1606 config.expectedDepth = 0.5f;
1607 config.expectedColor = kAlternativeColor;
1608 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_equal", "Dynamically set the depth compare operator to EQUAL", config));
1611 TestConfig config = baseConfig;
1612 config.depthCompareOpConfig.dynamicValue = vk::VK_COMPARE_OP_LESS_OR_EQUAL;
1613 config.meshParams[0].depth = 0.25f;
1614 config.expectedDepth = 0.25f;
1615 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));
1618 TestConfig config = baseConfig;
1619 config.depthCompareOpConfig.dynamicValue = vk::VK_COMPARE_OP_LESS_OR_EQUAL;
1620 config.meshParams[0].depth = 0.5f;
1621 config.expectedDepth = 0.5f;
1622 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));
1625 TestConfig config = baseConfig;
1626 config.depthCompareOpConfig.dynamicValue = vk::VK_COMPARE_OP_LESS_OR_EQUAL;
1627 config.meshParams[0].depth = 0.25f;
1628 // Draw another mesh with the same depth in front of it.
1629 config.meshParams.push_back(MeshParams(kAlternativeColor, 0.25f));
1630 config.expectedDepth = 0.25f;
1631 config.expectedColor = kAlternativeColor;
1632 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));
1635 TestConfig config = baseConfig;
1636 config.depthCompareOpConfig.dynamicValue = vk::VK_COMPARE_OP_GREATER_OR_EQUAL;
1637 config.meshParams[0].depth = 0.75f;
1638 config.expectedDepth = 0.75f;
1639 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));
1642 TestConfig config = baseConfig;
1643 config.depthCompareOpConfig.dynamicValue = vk::VK_COMPARE_OP_GREATER_OR_EQUAL;
1644 config.meshParams[0].depth = 0.5f;
1645 config.expectedDepth = 0.5f;
1646 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));
1649 TestConfig config = baseConfig;
1650 config.depthCompareOpConfig.dynamicValue = vk::VK_COMPARE_OP_GREATER_OR_EQUAL;
1651 config.meshParams[0].depth = 0.75f;
1652 // Draw another mesh with the same depth in front of it.
1653 config.meshParams.push_back(MeshParams(kAlternativeColor, 0.75f));
1654 config.expectedDepth = 0.75f;
1655 config.expectedColor = kAlternativeColor;
1656 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));
1659 TestConfig config = baseConfig;
1660 config.depthCompareOpConfig.dynamicValue = vk::VK_COMPARE_OP_NOT_EQUAL;
1662 // Draw first mesh in front.
1663 config.meshParams[0].depth = 0.25f;
1664 // Draw another mesh in the back, this should pass too.
1665 config.meshParams.push_back(MeshParams(kAlternativeColor, 0.5f));
1666 // Finally a new mesh with the same depth. This should not pass.
1667 config.meshParams.push_back(MeshParams(kDefaultTriangleColor, 0.5f));
1669 config.expectedColor = kAlternativeColor;
1670 config.expectedDepth = 0.5f;
1671 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_not_equal", "Dynamically set the depth compare operator to NOT_EQUAL", config));
1674 TestConfig config = baseConfig;
1675 config.depthCompareOpConfig.dynamicValue = vk::VK_COMPARE_OP_ALWAYS;
1677 config.meshParams[0].depth = 0.5f;
1678 config.expectedDepth = 0.5f;
1679 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_always_equal", "Dynamically set the depth compare operator to ALWAYS and draw with equal depth", config));
1681 config.meshParams[0].depth = 0.25f;
1682 config.expectedDepth = 0.25f;
1683 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_always_less", "Dynamically set the depth compare operator to ALWAYS and draw with less depth", config));
1685 config.meshParams[0].depth = 0.75f;
1686 config.expectedDepth = 0.75f;
1687 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_compare_always_greater", "Dynamically set the depth compare operator to ALWAYS and draw with greater depth", config));
1691 // Depth bounds test.
1693 TestConfig baseConfig(kOrdering);
1694 baseConfig.minDepthBounds = 0.25f;
1695 baseConfig.maxDepthBounds = 0.75f;
1696 baseConfig.meshParams[0].depth = 0.0f;
1699 TestConfig config = baseConfig;
1700 config.depthBoundsTestEnableConfig.staticValue = false;
1701 config.depthBoundsTestEnableConfig.dynamicValue = tcu::just(true);
1702 config.expectedColor = kDefaultClearColor;
1703 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_bounds_test_enable", "Dynamically enable the depth bounds test", config));
1706 TestConfig config = baseConfig;
1707 config.depthBoundsTestEnableConfig.staticValue = true;
1708 config.depthBoundsTestEnableConfig.dynamicValue = tcu::just(false);
1709 config.expectedColor = kDefaultTriangleColor;
1710 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "depth_bounds_test_disable", "Dynamically disable the depth bounds test", config));
1714 // Stencil test enable.
1716 TestConfig config(kOrdering);
1717 config.stencilTestEnableConfig.staticValue = false;
1718 config.stencilTestEnableConfig.dynamicValue = tcu::just(true);
1719 config.stencilOpConfig.staticValue.front().compareOp = vk::VK_COMPARE_OP_NEVER;
1720 config.expectedColor = kDefaultClearColor;
1721 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "stencil_test_enable", "Dynamically enable the stencil test", config));
1724 TestConfig config(kOrdering);
1725 config.stencilTestEnableConfig.staticValue = true;
1726 config.stencilTestEnableConfig.dynamicValue = tcu::just(false);
1727 config.stencilOpConfig.staticValue.front().compareOp = vk::VK_COMPARE_OP_NEVER;
1728 config.expectedColor = kDefaultTriangleColor;
1729 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, "stencil_test_disable", "Dynamically disable the stencil test", config));
1732 // Stencil operation. Many combinations are possible.
1736 vk::VkStencilFaceFlags face;
1740 { vk::VK_STENCIL_FACE_FRONT_BIT, "face_front" },
1741 { vk::VK_STENCIL_FACE_BACK_BIT, "face_back" },
1742 { vk::VK_STENCIL_FRONT_AND_BACK, "face_both_single" },
1743 { vk::VK_STENCIL_FACE_FLAG_BITS_MAX_ENUM, "face_both_dual" }, // MAX_ENUM is a placeholder.
1748 vk::VkCompareOp compareOp;
1752 { vk::VK_COMPARE_OP_NEVER, "xf" },
1753 { vk::VK_COMPARE_OP_LESS, "lt" },
1754 { vk::VK_COMPARE_OP_EQUAL, "eq" },
1755 { vk::VK_COMPARE_OP_LESS_OR_EQUAL, "le" },
1756 { vk::VK_COMPARE_OP_GREATER, "gt" },
1757 { vk::VK_COMPARE_OP_GREATER_OR_EQUAL, "ge" },
1758 { vk::VK_COMPARE_OP_ALWAYS, "xt" },
1761 using u8vec = std::vector<deUint8>;
1763 static const auto kMinVal = std::numeric_limits<deUint8>::min();
1764 static const auto kMaxVal = std::numeric_limits<deUint8>::max();
1765 static const auto kMidVal = static_cast<deUint8>(kMaxVal * 2u / 5u);
1766 static const auto kMinValI = static_cast<int>(kMinVal);
1767 static const auto kMaxValI = static_cast<int>(kMaxVal);
1771 vk::VkStencilOp stencilOp;
1773 u8vec clearValues; // One test per clear value interesting for this operation.
1774 vk::VkStencilOp incompatibleOp; // Alternative operation giving incompatible results for the given values.
1777 { vk::VK_STENCIL_OP_KEEP, "keep", u8vec{kMidVal}, vk::VK_STENCIL_OP_ZERO },
1778 { vk::VK_STENCIL_OP_ZERO, "zero", u8vec{kMidVal}, vk::VK_STENCIL_OP_KEEP },
1779 { vk::VK_STENCIL_OP_REPLACE, "replace", u8vec{kMidVal}, vk::VK_STENCIL_OP_ZERO },
1780 { vk::VK_STENCIL_OP_INCREMENT_AND_CLAMP, "inc_clamp", u8vec{kMaxVal - 1, kMaxVal}, vk::VK_STENCIL_OP_ZERO },
1781 { vk::VK_STENCIL_OP_DECREMENT_AND_CLAMP, "dec_clamp", u8vec{kMinVal + 1, kMinVal}, vk::VK_STENCIL_OP_INCREMENT_AND_CLAMP },
1782 { vk::VK_STENCIL_OP_INVERT, "invert", u8vec{kMidVal}, vk::VK_STENCIL_OP_ZERO },
1783 { vk::VK_STENCIL_OP_INCREMENT_AND_WRAP, "inc_wrap", u8vec{kMaxVal - 1, kMaxVal}, vk::VK_STENCIL_OP_KEEP },
1784 { vk::VK_STENCIL_OP_DECREMENT_AND_WRAP, "dec_wrap", u8vec{kMinVal + 1, kMinVal}, vk::VK_STENCIL_OP_KEEP },
1787 for (int facesIdx = 0; facesIdx < DE_LENGTH_OF_ARRAY(kFaces); ++facesIdx)
1788 for (int compareIdx = 0; compareIdx < DE_LENGTH_OF_ARRAY(kCompare); ++compareIdx)
1789 for (int opIdx = 0; opIdx < DE_LENGTH_OF_ARRAY(kStencilOps); ++opIdx)
1791 const auto& face = kFaces[facesIdx];
1792 const auto& compare = kCompare[compareIdx];
1793 const auto& op = kStencilOps[opIdx];
1795 // Try clearing the stencil value with different values.
1796 for (const auto clearVal : op.clearValues)
1798 // Use interesting values as the reference stencil value.
1799 for (int delta = -1; delta <= 1; ++delta)
1801 const int refVal = clearVal + delta;
1802 if (refVal < kMinValI || refVal > kMaxValI)
1805 const auto refValU8 = static_cast<deUint8>(refVal);
1806 const auto refValU32 = static_cast<deUint32>(refVal);
1808 // Calculate outcome of the stencil test itself.
1809 const bool wouldPass = stencilPasses(compare.compareOp, clearVal, refValU8);
1811 // If the test passes, use an additional variant for the depthFail operation.
1812 const int subCases = (wouldPass ? 2 : 1);
1814 for (int subCaseIdx = 0; subCaseIdx < subCases; ++subCaseIdx)
1816 const bool depthFail = (subCaseIdx > 0); // depthFail would be the second variant.
1817 const bool globalPass = (wouldPass && !depthFail); // Global result of the stencil+depth test.
1819 // Start tuning test parameters.
1820 TestConfig config(kOrdering);
1822 // No face culling is applied by default, so both the front and back operations could apply depending on the mesh.
1823 if (face.face == vk::VK_STENCIL_FACE_FRONT_BIT)
1825 // Default parameters are OK.
1827 else if (face.face == vk::VK_STENCIL_FACE_BACK_BIT)
1829 // Reverse the mesh so it applies the back operation.
1830 config.meshParams[0].reversed = true;
1832 else // Front and back.
1834 // Draw both a front and a back-facing mesh so both are applied.
1835 // The first mesh will be drawn in the top half and the second mesh in the bottom half.
1837 // Make the second mesh a reversed copy of the first mesh.
1838 config.meshParams.push_back(config.meshParams.front());
1839 config.meshParams.back().reversed = true;
1841 // Apply scale and offset to the top mesh.
1842 config.meshParams.front().scaleY = 0.5f;
1843 config.meshParams.front().offsetY = -0.5f;
1845 // Apply scale and offset to the bottom mesh.
1846 config.meshParams.back().scaleY = 0.5f;
1847 config.meshParams.back().offsetY = 0.5f;
1850 // Enable the stencil test.
1851 config.stencilTestEnableConfig.staticValue = true;
1853 // Set dynamic configuration.
1854 StencilOpParams dynamicStencilConfig;
1855 dynamicStencilConfig.faceMask = face.face;
1856 dynamicStencilConfig.compareOp = compare.compareOp;
1857 dynamicStencilConfig.failOp = vk::VK_STENCIL_OP_MAX_ENUM;
1858 dynamicStencilConfig.passOp = vk::VK_STENCIL_OP_MAX_ENUM;
1859 dynamicStencilConfig.depthFailOp = vk::VK_STENCIL_OP_MAX_ENUM;
1861 // Set operations so only the appropriate operation for this case gives the right result.
1862 vk::VkStencilOp* activeOp = nullptr;
1863 vk::VkStencilOp* inactiveOps[2] = { nullptr, nullptr };
1868 activeOp = &dynamicStencilConfig.depthFailOp;
1869 inactiveOps[0] = &dynamicStencilConfig.passOp;
1870 inactiveOps[1] = &dynamicStencilConfig.failOp;
1874 activeOp = &dynamicStencilConfig.passOp;
1875 inactiveOps[0] = &dynamicStencilConfig.depthFailOp;
1876 inactiveOps[1] = &dynamicStencilConfig.failOp;
1881 activeOp = &dynamicStencilConfig.failOp;
1882 inactiveOps[0] = &dynamicStencilConfig.passOp;
1883 inactiveOps[1] = &dynamicStencilConfig.depthFailOp;
1886 *activeOp = op.stencilOp;
1887 *inactiveOps[0] = op.incompatibleOp;
1888 *inactiveOps[1] = op.incompatibleOp;
1890 // Make sure all ops have been configured properly.
1891 DE_ASSERT(dynamicStencilConfig.failOp != vk::VK_STENCIL_OP_MAX_ENUM);
1892 DE_ASSERT(dynamicStencilConfig.passOp != vk::VK_STENCIL_OP_MAX_ENUM);
1893 DE_ASSERT(dynamicStencilConfig.depthFailOp != vk::VK_STENCIL_OP_MAX_ENUM);
1895 // Set an incompatible static operation too.
1896 auto& staticStencilConfig = config.stencilOpConfig.staticValue.front();
1897 staticStencilConfig.faceMask = face.face;
1898 staticStencilConfig.compareOp = (globalPass ? vk::VK_COMPARE_OP_NEVER : vk::VK_COMPARE_OP_ALWAYS);
1899 staticStencilConfig.passOp = op.incompatibleOp;
1900 staticStencilConfig.failOp = op.incompatibleOp;
1901 staticStencilConfig.depthFailOp = op.incompatibleOp;
1903 // Set dynamic configuration.
1904 StencilOpVec stencilOps;
1905 stencilOps.push_back(dynamicStencilConfig);
1907 if (stencilOps.front().faceMask == vk::VK_STENCIL_FACE_FLAG_BITS_MAX_ENUM)
1909 // This is the dual case. We will set the front and back face values with two separate calls.
1910 stencilOps.push_back(stencilOps.front());
1911 stencilOps.front().faceMask = vk::VK_STENCIL_FACE_FRONT_BIT;
1912 stencilOps.back().faceMask = vk::VK_STENCIL_FACE_BACK_BIT;
1915 config.stencilOpConfig.dynamicValue = tcu::just(stencilOps);
1916 config.clearStencilValue = clearVal;
1917 config.referenceStencil = refValU32;
1921 // Enable depth test and make it fail.
1922 config.depthTestEnableConfig.staticValue = true;
1923 config.clearDepthValue = 0.5f;
1924 config.depthCompareOpConfig.staticValue = vk::VK_COMPARE_OP_LESS;
1926 for (auto& meshPar : config.meshParams)
1927 meshPar.depth = 0.75f;
1930 // Set expected outcome.
1931 config.expectedColor = (globalPass ? kDefaultTriangleColor : kDefaultClearColor);
1932 config.expectedDepth = config.clearDepthValue; // No depth writing by default.
1933 config.expectedStencil = stencilResult(op.stencilOp, clearVal, refValU8, kMinVal, kMaxVal);
1935 const std::string testName = std::string("stencil_state")
1937 + "_" + compare.name
1939 + "_clear_" + de::toString(static_cast<int>(clearVal))
1940 + "_ref_" + de::toString(refVal)
1941 + "_" + (wouldPass ? (depthFail ? "depthfail" : "pass") : "fail");
1943 orderingGroup->addChild(new ExtendedDynamicStateTest(testCtx, testName, "Dynamically configure stencil test, variant " + testName, config));
1950 extendedDynamicStateGroup->addChild(orderingGroup.release());
1953 return extendedDynamicStateGroup.release();