xref: /aosp_15_r20/external/deqp/external/vulkancts/modules/vulkan/pipeline/vktPipelineStencilTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2015 The Khronos Group Inc.
6  * Copyright (c) 2015 Imagination Technologies Ltd.
7  * Copyright (c) 2023 LunarG, Inc.
8  * Copyright (c) 2023 Nintendo
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  *      http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  *
22  *//*!
23  * \file
24  * \brief Stencil Tests
25  *//*--------------------------------------------------------------------*/
26 
27 #include "vktPipelineStencilTests.hpp"
28 #include "vktPipelineClearUtil.hpp"
29 #include "vktPipelineImageUtil.hpp"
30 #include "vktPipelineVertexUtil.hpp"
31 #include "vktPipelineReferenceRenderer.hpp"
32 #include "vktPipelineUniqueRandomIterator.hpp"
33 #include "vktTestCase.hpp"
34 #include "vkImageUtil.hpp"
35 #include "vkMemUtil.hpp"
36 #include "vkPrograms.hpp"
37 #include "vkQueryUtil.hpp"
38 #include "vkRef.hpp"
39 #include "vkRefUtil.hpp"
40 #include "vkTypeUtil.hpp"
41 #include "vkCmdUtil.hpp"
42 #include "vkObjUtil.hpp"
43 #include "tcuImageCompare.hpp"
44 #include "deMemory.h"
45 #include "deRandom.hpp"
46 #include "deStringUtil.hpp"
47 #include "deUniquePtr.hpp"
48 
49 #include <algorithm>
50 #include <sstream>
51 #include <vector>
52 
53 namespace vkt
54 {
55 namespace pipeline
56 {
57 
58 using namespace vk;
59 
60 namespace
61 {
62 
isSupportedDepthStencilFormat(const InstanceInterface & instanceInterface,VkPhysicalDevice device,VkFormat format)63 bool isSupportedDepthStencilFormat(const InstanceInterface &instanceInterface, VkPhysicalDevice device, VkFormat format)
64 {
65     VkFormatProperties formatProps;
66 
67     instanceInterface.getPhysicalDeviceFormatProperties(device, format, &formatProps);
68 
69     return (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0;
70 }
71 
72 class StencilOpStateUniqueRandomIterator : public UniqueRandomIterator<VkStencilOpState>
73 {
74 public:
75     StencilOpStateUniqueRandomIterator(int seed);
~StencilOpStateUniqueRandomIterator(void)76     virtual ~StencilOpStateUniqueRandomIterator(void)
77     {
78     }
79     virtual VkStencilOpState getIndexedValue(uint32_t index);
80 
81 private:
82     // Pre-calculated constants
83     const static uint32_t s_stencilOpsLength;
84     const static uint32_t s_stencilOpsLength2;
85     const static uint32_t s_stencilOpsLength3;
86     const static uint32_t s_compareOpsLength;
87 
88     // Total number of cross-combinations of (stencilFailOp x stencilPassOp x stencilDepthFailOp x stencilCompareOp)
89     const static uint32_t s_totalStencilOpStates;
90 };
91 
92 class StencilTest : public vkt::TestCase
93 {
94 public:
95     enum
96     {
97         QUAD_COUNT = 4
98     };
99 
100     struct StencilStateConfig
101     {
102         uint32_t frontReadMask;
103         uint32_t frontWriteMask;
104         uint32_t frontRef;
105 
106         uint32_t backReadMask;
107         uint32_t backWriteMask;
108         uint32_t backRef;
109     };
110 
111     const static StencilStateConfig s_stencilStateConfigs[QUAD_COUNT];
112     const static float s_quadDepths[QUAD_COUNT];
113 
114     StencilTest(tcu::TestContext &testContext, const std::string &name,
115                 PipelineConstructionType pipelineConstructionType, VkFormat stencilFormat,
116                 const VkStencilOpState &stencilOpStateFront, const VkStencilOpState &stencilOpStateBack,
117                 const bool colorAttachmentEnable, const bool separateDepthStencilLayouts);
118     virtual ~StencilTest(void) = default;
119     virtual void initPrograms(SourceCollections &sourceCollections) const;
120     virtual void checkSupport(Context &context) const;
121     virtual TestInstance *createInstance(Context &context) const;
122 
123 private:
124     PipelineConstructionType m_pipelineConstructionType;
125     VkFormat m_stencilFormat;
126     const VkStencilOpState m_stencilOpStateFront;
127     const VkStencilOpState m_stencilOpStateBack;
128     const bool m_colorAttachmentEnable;
129     const bool m_separateDepthStencilLayouts;
130 };
131 
132 class StencilTestInstance : public vkt::TestInstance
133 {
134 public:
135     StencilTestInstance(Context &context, PipelineConstructionType pipelineConstructionType, VkFormat stencilFormat,
136                         const VkStencilOpState &stencilOpStatesFront, const VkStencilOpState &stencilOpStatesBack,
137                         const bool colorAttachmentEnable, const bool separateDepthStencilLayouts);
138     virtual ~StencilTestInstance(void) = default;
139     virtual tcu::TestStatus iterate(void);
140 
141 private:
142     tcu::TestStatus verifyImage(void);
143 
144     VkStencilOpState m_stencilOpStateFront;
145     VkStencilOpState m_stencilOpStateBack;
146     const bool m_colorAttachmentEnable;
147     const bool m_separateDepthStencilLayouts;
148     const tcu::UVec2 m_renderSize;
149     const VkFormat m_colorFormat;
150     const VkFormat m_stencilFormat;
151     VkImageSubresourceRange m_stencilImageSubresourceRange;
152 
153     VkImageCreateInfo m_colorImageCreateInfo;
154     Move<VkImage> m_colorImage;
155     de::MovePtr<Allocation> m_colorImageAlloc;
156     Move<VkImage> m_stencilImage;
157     de::MovePtr<Allocation> m_stencilImageAlloc;
158     Move<VkImageView> m_colorAttachmentView;
159     Move<VkImageView> m_stencilAttachmentView;
160     RenderPassWrapper m_renderPass;
161     Move<VkFramebuffer> m_framebuffer;
162 
163     ShaderWrapper m_vertexShaderModule;
164     ShaderWrapper m_fragmentShaderModule;
165 
166     Move<VkBuffer> m_vertexBuffer;
167     std::vector<Vertex4RGBA> m_vertices;
168     de::MovePtr<Allocation> m_vertexBufferAlloc;
169 
170     PipelineLayoutWrapper m_pipelineLayout;
171     GraphicsPipelineWrapper m_graphicsPipelines[StencilTest::QUAD_COUNT];
172 
173     Move<VkCommandPool> m_cmdPool;
174     Move<VkCommandBuffer> m_cmdBuffer;
175 };
176 
177 const VkStencilOp stencilOps[] = {VK_STENCIL_OP_KEEP,
178                                   VK_STENCIL_OP_ZERO,
179                                   VK_STENCIL_OP_REPLACE,
180                                   VK_STENCIL_OP_INCREMENT_AND_CLAMP,
181                                   VK_STENCIL_OP_DECREMENT_AND_CLAMP,
182                                   VK_STENCIL_OP_INVERT,
183                                   VK_STENCIL_OP_INCREMENT_AND_WRAP,
184                                   VK_STENCIL_OP_DECREMENT_AND_WRAP};
185 
186 const VkCompareOp compareOps[] = {VK_COMPARE_OP_NEVER,
187                                   VK_COMPARE_OP_LESS,
188                                   VK_COMPARE_OP_EQUAL,
189                                   VK_COMPARE_OP_LESS_OR_EQUAL,
190                                   VK_COMPARE_OP_GREATER,
191                                   VK_COMPARE_OP_NOT_EQUAL,
192                                   VK_COMPARE_OP_GREATER_OR_EQUAL,
193                                   VK_COMPARE_OP_ALWAYS};
194 
195 // StencilOpStateUniqueRandomIterator
196 
197 const uint32_t StencilOpStateUniqueRandomIterator::s_stencilOpsLength     = DE_LENGTH_OF_ARRAY(stencilOps);
198 const uint32_t StencilOpStateUniqueRandomIterator::s_stencilOpsLength2    = s_stencilOpsLength * s_stencilOpsLength;
199 const uint32_t StencilOpStateUniqueRandomIterator::s_stencilOpsLength3    = s_stencilOpsLength2 * s_stencilOpsLength;
200 const uint32_t StencilOpStateUniqueRandomIterator::s_compareOpsLength     = DE_LENGTH_OF_ARRAY(compareOps);
201 const uint32_t StencilOpStateUniqueRandomIterator::s_totalStencilOpStates = s_stencilOpsLength3 * s_compareOpsLength;
202 
StencilOpStateUniqueRandomIterator(int seed)203 StencilOpStateUniqueRandomIterator::StencilOpStateUniqueRandomIterator(int seed)
204     : UniqueRandomIterator<VkStencilOpState>(s_totalStencilOpStates, s_totalStencilOpStates, seed)
205 {
206 }
207 
getIndexedValue(uint32_t index)208 VkStencilOpState StencilOpStateUniqueRandomIterator::getIndexedValue(uint32_t index)
209 {
210     const uint32_t stencilCompareOpIndex    = index / s_stencilOpsLength3;
211     const uint32_t stencilCompareOpSeqIndex = stencilCompareOpIndex * s_stencilOpsLength3;
212 
213     const uint32_t stencilDepthFailOpIndex    = (index - stencilCompareOpSeqIndex) / s_stencilOpsLength2;
214     const uint32_t stencilDepthFailOpSeqIndex = stencilDepthFailOpIndex * s_stencilOpsLength2;
215 
216     const uint32_t stencilPassOpIndex =
217         (index - stencilCompareOpSeqIndex - stencilDepthFailOpSeqIndex) / s_stencilOpsLength;
218     const uint32_t stencilPassOpSeqIndex = stencilPassOpIndex * s_stencilOpsLength;
219 
220     const uint32_t stencilFailOpIndex =
221         index - stencilCompareOpSeqIndex - stencilDepthFailOpSeqIndex - stencilPassOpSeqIndex;
222 
223     const VkStencilOpState stencilOpState = {
224         stencilOps[stencilFailOpIndex],      // VkStencilOp failOp;
225         stencilOps[stencilPassOpIndex],      // VkStencilOp passOp;
226         stencilOps[stencilDepthFailOpIndex], // VkStencilOp depthFailOp;
227         compareOps[stencilCompareOpIndex],   // VkCompareOp compareOp;
228         0x0,                                 // uint32_t compareMask;
229         0x0,                                 // uint32_t writeMask;
230         0x0                                  // uint32_t reference;
231     };
232 
233     return stencilOpState;
234 }
235 
236 // StencilTest
237 
238 const StencilTest::StencilStateConfig StencilTest::s_stencilStateConfigs[QUAD_COUNT] = {
239     //    frontReadMask    frontWriteMask        frontRef        backReadMask    backWriteMask    backRef
240     {0xFF, 0xFF, 0xAB, 0xF0, 0xFF, 0xFF},
241     {0xFF, 0xF0, 0xCD, 0xF0, 0xF0, 0xEF},
242     {0xF0, 0x0F, 0xEF, 0xFF, 0x0F, 0xCD},
243     {0xF0, 0x01, 0xFF, 0xFF, 0x01, 0xAB}};
244 
245 const float StencilTest::s_quadDepths[QUAD_COUNT] = {0.1f, 0.0f, 0.3f, 0.2f};
246 
StencilTest(tcu::TestContext & testContext,const std::string & name,PipelineConstructionType pipelineConstructionType,VkFormat stencilFormat,const VkStencilOpState & stencilOpStateFront,const VkStencilOpState & stencilOpStateBack,const bool colorAttachmentEnable,const bool separateDepthStencilLayouts)247 StencilTest::StencilTest(tcu::TestContext &testContext, const std::string &name,
248                          PipelineConstructionType pipelineConstructionType, VkFormat stencilFormat,
249                          const VkStencilOpState &stencilOpStateFront, const VkStencilOpState &stencilOpStateBack,
250                          const bool colorAttachmentEnable, const bool separateDepthStencilLayouts)
251     : vkt::TestCase(testContext, name)
252     , m_pipelineConstructionType(pipelineConstructionType)
253     , m_stencilFormat(stencilFormat)
254     , m_stencilOpStateFront(stencilOpStateFront)
255     , m_stencilOpStateBack(stencilOpStateBack)
256     , m_colorAttachmentEnable(colorAttachmentEnable)
257     , m_separateDepthStencilLayouts(separateDepthStencilLayouts)
258 {
259 }
260 
checkSupport(Context & context) const261 void StencilTest::checkSupport(Context &context) const
262 {
263     if (!isSupportedDepthStencilFormat(context.getInstanceInterface(), context.getPhysicalDevice(), m_stencilFormat))
264         throw tcu::NotSupportedError(std::string("Unsupported depth/stencil format: ") +
265                                      getFormatName(m_stencilFormat));
266 
267     if (m_separateDepthStencilLayouts &&
268         !context.isDeviceFunctionalitySupported("VK_KHR_separate_depth_stencil_layouts"))
269         TCU_THROW(NotSupportedError, "VK_KHR_separate_depth_stencil_layouts is not supported");
270 
271     checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(),
272                                           m_pipelineConstructionType);
273 
274 #ifndef CTS_USES_VULKANSC
275     if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
276         !context.getPortabilitySubsetFeatures().separateStencilMaskRef)
277         TCU_THROW(
278             NotSupportedError,
279             "VK_KHR_portability_subset: Separate stencil mask references are not supported by this implementation");
280 #endif // CTS_USES_VULKANSC
281 }
282 
createInstance(Context & context) const283 TestInstance *StencilTest::createInstance(Context &context) const
284 {
285     return new StencilTestInstance(context, m_pipelineConstructionType, m_stencilFormat, m_stencilOpStateFront,
286                                    m_stencilOpStateBack, m_colorAttachmentEnable, m_separateDepthStencilLayouts);
287 }
288 
initPrograms(SourceCollections & sourceCollections) const289 void StencilTest::initPrograms(SourceCollections &sourceCollections) const
290 {
291     if (m_colorAttachmentEnable)
292     {
293         sourceCollections.glslSources.add("color_vert")
294             << glu::VertexSource("#version 310 es\n"
295                                  "layout(location = 0) in vec4 position;\n"
296                                  "layout(location = 1) in vec4 color;\n"
297                                  "layout(location = 0) out highp vec4 vtxColor;\n"
298                                  "void main (void)\n"
299                                  "{\n"
300                                  "    gl_Position = position;\n"
301                                  "    vtxColor = color;\n"
302                                  "}\n");
303 
304         sourceCollections.glslSources.add("color_frag")
305             << glu::FragmentSource("#version 310 es\n"
306                                    "layout(location = 0) in highp vec4 vtxColor;\n"
307                                    "layout(location = 0) out highp vec4 fragColor;\n"
308                                    "void main (void)\n"
309                                    "{\n"
310                                    "    fragColor = vtxColor;\n"
311                                    "}\n");
312     }
313     else
314     {
315         sourceCollections.glslSources.add("color_vert") << glu::VertexSource("#version 310 es\n"
316                                                                              "layout(location = 0) in vec4 position;\n"
317                                                                              "layout(location = 1) in vec4 color;\n"
318                                                                              "void main (void)\n"
319                                                                              "{\n"
320                                                                              "    gl_Position = position;\n"
321                                                                              "}\n");
322     }
323 }
324 
325 // StencilTestInstance
326 
StencilTestInstance(Context & context,PipelineConstructionType pipelineConstructionType,VkFormat stencilFormat,const VkStencilOpState & stencilOpStateFront,const VkStencilOpState & stencilOpStateBack,const bool colorAttachmentEnable,const bool separateDepthStencilLayouts)327 StencilTestInstance::StencilTestInstance(Context &context, PipelineConstructionType pipelineConstructionType,
328                                          VkFormat stencilFormat, const VkStencilOpState &stencilOpStateFront,
329                                          const VkStencilOpState &stencilOpStateBack, const bool colorAttachmentEnable,
330                                          const bool separateDepthStencilLayouts)
331     : vkt::TestInstance(context)
332     , m_stencilOpStateFront(stencilOpStateFront)
333     , m_stencilOpStateBack(stencilOpStateBack)
334     , m_colorAttachmentEnable(colorAttachmentEnable)
335     , m_separateDepthStencilLayouts(separateDepthStencilLayouts)
336     , m_renderSize(32, 32)
337     , m_colorFormat(colorAttachmentEnable ? VK_FORMAT_R8G8B8A8_UNORM : VK_FORMAT_UNDEFINED)
338     , m_stencilFormat(stencilFormat)
339     , m_graphicsPipelines{{context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(),
340                            context.getDevice(), context.getDeviceExtensions(), pipelineConstructionType},
341                           {context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(),
342                            context.getDevice(), context.getDeviceExtensions(), pipelineConstructionType},
343                           {context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(),
344                            context.getDevice(), context.getDeviceExtensions(), pipelineConstructionType},
345                           {context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(),
346                            context.getDevice(), context.getDeviceExtensions(), pipelineConstructionType}}
347 {
348     const DeviceInterface &vk       = context.getDeviceInterface();
349     const VkDevice vkDevice         = context.getDevice();
350     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
351     SimpleAllocator memAlloc(
352         vk, vkDevice, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()));
353     const VkComponentMapping componentMappingRGBA = {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G,
354                                                      VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A};
355 
356     // Create color image
357     if (m_colorAttachmentEnable)
358     {
359         const VkImageCreateInfo colorImageParams = {
360             VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                                   // VkStructureType sType;
361             DE_NULL,                                                               // const void* pNext;
362             0u,                                                                    // VkImageCreateFlags flags;
363             VK_IMAGE_TYPE_2D,                                                      // VkImageType imageType;
364             m_colorFormat,                                                         // VkFormat format;
365             {m_renderSize.x(), m_renderSize.y(), 1u},                              // VkExtent3D extent;
366             1u,                                                                    // uint32_t mipLevels;
367             1u,                                                                    // uint32_t arrayLayers;
368             VK_SAMPLE_COUNT_1_BIT,                                                 // VkSampleCountFlagBits samples;
369             VK_IMAGE_TILING_OPTIMAL,                                               // VkImageTiling tiling;
370             VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage;
371             VK_SHARING_MODE_EXCLUSIVE,                                             // VkSharingMode sharingMode;
372             1u,                                                                    // uint32_t queueFamilyIndexCount;
373             &queueFamilyIndex,        // const uint32_t* pQueueFamilyIndices;
374             VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
375         };
376 
377         m_colorImageCreateInfo = colorImageParams;
378         m_colorImage           = createImage(vk, vkDevice, &m_colorImageCreateInfo);
379 
380         // Allocate and bind color image memory
381         m_colorImageAlloc =
382             memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any);
383         VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(),
384                                     m_colorImageAlloc->getOffset()));
385     }
386 
387     // Create stencil image
388     {
389         const VkImageUsageFlags usageFlags =
390             VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
391 
392         const VkImageCreateInfo stencilImageParams = {
393             VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,      // VkStructureType sType;
394             DE_NULL,                                  // const void* pNext;
395             0u,                                       // VkImageCreateFlags flags;
396             VK_IMAGE_TYPE_2D,                         // VkImageType imageType;
397             m_stencilFormat,                          // VkFormat format;
398             {m_renderSize.x(), m_renderSize.y(), 1u}, // VkExtent3D extent;
399             1u,                                       // uint32_t mipLevels;
400             1u,                                       // uint32_t arrayLayers;
401             VK_SAMPLE_COUNT_1_BIT,                    // VkSampleCountFlagBits samples;
402             VK_IMAGE_TILING_OPTIMAL,                  // VkImageTiling tiling;
403             usageFlags,                               // VkImageUsageFlags usage;
404             VK_SHARING_MODE_EXCLUSIVE,                // VkSharingMode sharingMode;
405             1u,                                       // uint32_t queueFamilyIndexCount;
406             &queueFamilyIndex,                        // const uint32_t* pQueueFamilyIndices;
407             VK_IMAGE_LAYOUT_UNDEFINED                 // VkImageLayout initialLayout;
408         };
409 
410         m_stencilImage = createImage(vk, vkDevice, &stencilImageParams);
411 
412         // Allocate and bind stencil image memory
413         m_stencilImageAlloc =
414             memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_stencilImage), MemoryRequirement::Any);
415         VK_CHECK(vk.bindImageMemory(vkDevice, *m_stencilImage, m_stencilImageAlloc->getMemory(),
416                                     m_stencilImageAlloc->getOffset()));
417 
418         const VkImageAspectFlags aspect = (mapVkFormat(m_stencilFormat).order == tcu::TextureFormat::DS ?
419                                                VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_DEPTH_BIT :
420                                                VK_IMAGE_ASPECT_STENCIL_BIT);
421         m_stencilImageSubresourceRange =
422             makeImageSubresourceRange(aspect, 0u, stencilImageParams.mipLevels, 0u, stencilImageParams.arrayLayers);
423     }
424 
425     // Create color attachment view
426     if (m_colorAttachmentEnable)
427     {
428         const VkImageViewCreateInfo colorAttachmentViewParams = {
429             VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,   // VkStructureType sType;
430             DE_NULL,                                    // const void* pNext;
431             0u,                                         // VkImageViewCreateFlags flags;
432             *m_colorImage,                              // VkImage image;
433             VK_IMAGE_VIEW_TYPE_2D,                      // VkImageViewType viewType;
434             m_colorFormat,                              // VkFormat format;
435             componentMappingRGBA,                       // VkComponentMapping components;
436             {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u} // VkImageSubresourceRange subresourceRange;
437         };
438 
439         m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams);
440     }
441 
442     // Create stencil attachment view
443     {
444         const VkImageViewCreateInfo stencilAttachmentViewParams = {
445             VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
446             DE_NULL,                                  // const void* pNext;
447             0u,                                       // VkImageViewCreateFlags flags;
448             *m_stencilImage,                          // VkImage image;
449             VK_IMAGE_VIEW_TYPE_2D,                    // VkImageViewType viewType;
450             m_stencilFormat,                          // VkFormat format;
451             componentMappingRGBA,                     // VkComponentMapping components;
452             m_stencilImageSubresourceRange,           // VkImageSubresourceRange subresourceRange;
453         };
454 
455         m_stencilAttachmentView = createImageView(vk, vkDevice, &stencilAttachmentViewParams);
456     }
457 
458     // Create render pass
459     m_renderPass = RenderPassWrapper(pipelineConstructionType, vk, vkDevice, m_colorFormat, m_stencilFormat);
460 
461     // Create framebuffer
462     {
463         std::vector<VkImage> images;
464         std::vector<VkImageView> attachmentBindInfos;
465 
466         if (m_colorAttachmentEnable)
467         {
468             images.push_back(*m_colorImage);
469             attachmentBindInfos.push_back(*m_colorAttachmentView);
470         }
471 
472         images.push_back(*m_stencilImage);
473         attachmentBindInfos.push_back(*m_stencilAttachmentView);
474 
475         const VkFramebufferCreateInfo framebufferParams = {
476             VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
477             DE_NULL,                                   // const void* pNext;
478             0u,                                        // VkFramebufferCreateFlags flags;
479             *m_renderPass,                             // VkRenderPass renderPass;
480             (uint32_t)attachmentBindInfos.size(),      // uint32_t attachmentCount;
481             attachmentBindInfos.data(),                // const VkImageView* pAttachments;
482             (uint32_t)m_renderSize.x(),                // uint32_t width;
483             (uint32_t)m_renderSize.y(),                // uint32_t height;
484             1u                                         // uint32_t layers;
485         };
486 
487         m_renderPass.createFramebuffer(vk, vkDevice, &framebufferParams, images);
488     }
489 
490     // Create pipeline layout
491     {
492         const VkPipelineLayoutCreateInfo pipelineLayoutParams = {
493             VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
494             DE_NULL,                                       // const void* pNext;
495             0u,                                            // VkPipelineLayoutCreateFlags flags;
496             0u,                                            // uint32_t setLayoutCount;
497             DE_NULL,                                       // const VkDescriptorSetLayout* pSetLayouts;
498             0u,                                            // uint32_t pushConstantRangeCount;
499             DE_NULL                                        // const VkPushConstantRange* pPushConstantRanges;
500         };
501 
502         m_pipelineLayout = PipelineLayoutWrapper(pipelineConstructionType, vk, vkDevice, &pipelineLayoutParams);
503     }
504 
505     m_vertexShaderModule = ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("color_vert"), 0);
506     if (m_colorAttachmentEnable)
507         m_fragmentShaderModule = ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("color_frag"), 0);
508 
509     // Create pipeline
510     {
511         const VkVertexInputBindingDescription vertexInputBindingDescription{
512             0u,                         // uint32_t binding;
513             sizeof(Vertex4RGBA),        // uint32_t strideInBytes;
514             VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputStepRate inputRate;
515         };
516 
517         const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2]{
518             {
519                 0u,                            // uint32_t location;
520                 0u,                            // uint32_t binding;
521                 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
522                 0u                             // uint32_t offsetInBytes;
523             },
524             {
525                 1u,                            // uint32_t location;
526                 0u,                            // uint32_t binding;
527                 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
528                 offsetof(Vertex4RGBA, color),  // uint32_t offsetInBytes;
529             }};
530 
531         const VkPipelineVertexInputStateCreateInfo vertexInputStateParams{
532             VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
533             DE_NULL,                                                   // const void* pNext;
534             0u,                                                        // VkPipelineVertexInputStateCreateFlags flags;
535             1u,                                                        // uint32_t vertexBindingDescriptionCount;
536             &vertexInputBindingDescription,  // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
537             2u,                              // uint32_t vertexAttributeDescriptionCount;
538             vertexInputAttributeDescriptions // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
539         };
540 
541         const std::vector<VkViewport> viewports{makeViewport(m_renderSize)};
542         const std::vector<VkRect2D> scissors{makeRect2D(m_renderSize)};
543 
544         const bool isDepthEnabled = (vk::mapVkFormat(m_stencilFormat).order != tcu::TextureFormat::S);
545 
546         VkPipelineDepthStencilStateCreateInfo depthStencilStateParams{
547             VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
548             DE_NULL,                                                    // const void* pNext;
549             0u,                                                         // VkPipelineDepthStencilStateCreateFlags flags;
550             isDepthEnabled,                                             // VkBool32 depthTestEnable;
551             isDepthEnabled,                                             // VkBool32 depthWriteEnable;
552             VK_COMPARE_OP_LESS,                                         // VkCompareOp depthCompareOp;
553             false,                                                      // VkBool32 depthBoundsTestEnable;
554             true,                                                       // VkBool32 stencilTestEnable;
555             m_stencilOpStateFront,                                      // VkStencilOpState front;
556             m_stencilOpStateBack,                                       // VkStencilOpState back;
557             0.0f,                                                       // float minDepthBounds;
558             1.0f                                                        // float maxDepthBounds;
559         };
560 
561         // Make sure rasterization is not disabled when the fragment shader is missing.
562         const vk::VkPipelineRasterizationStateCreateInfo rasterizationStateParams{
563             vk::VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
564             nullptr,                                                        // const void* pNext;
565             0u,                                  // VkPipelineRasterizationStateCreateFlags flags;
566             VK_FALSE,                            // VkBool32 depthClampEnable;
567             VK_FALSE,                            // VkBool32 rasterizerDiscardEnable;
568             vk::VK_POLYGON_MODE_FILL,            // VkPolygonMode polygonMode;
569             vk::VK_CULL_MODE_NONE,               // VkCullModeFlags cullMode;
570             vk::VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
571             VK_FALSE,                            // VkBool32 depthBiasEnable;
572             0.0f,                                // float depthBiasConstantFactor;
573             0.0f,                                // float depthBiasClamp;
574             0.0f,                                // float depthBiasSlopeFactor;
575             1.0f,                                // float lineWidth;
576         };
577 
578         const vk::VkPipelineColorBlendAttachmentState blendState{
579             VK_FALSE,
580             VK_BLEND_FACTOR_ONE,
581             VK_BLEND_FACTOR_ONE,
582             VK_BLEND_OP_ADD,
583             VK_BLEND_FACTOR_ONE,
584             VK_BLEND_FACTOR_ONE,
585             VK_BLEND_OP_ADD,
586             VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT,
587 
588         };
589         const vk::VkPipelineColorBlendStateCreateInfo colorBlendStateParams{
590             vk::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType                                sType
591             DE_NULL,                           // const void*                                    pNext
592             0u,                                // VkPipelineColorBlendStateCreateFlags            flags
593             VK_FALSE,                          // VkBool32                                        logicOpEnable
594             vk::VK_LOGIC_OP_CLEAR,             // VkLogicOp                                    logicOp
595             m_colorAttachmentEnable ? 1u : 0u, // uint32_t                                        attachmentCount
596             &blendState,                       // const VkPipelineColorBlendAttachmentState*    pAttachments
597             {1.0f, 1.0f, 1.0f, 1.0f}           // float                                        blendConstants[4]
598         };
599 
600         // Setup different stencil masks and refs in each quad
601         for (int quadNdx = 0; quadNdx < StencilTest::QUAD_COUNT; quadNdx++)
602         {
603             const StencilTest::StencilStateConfig &config = StencilTest::s_stencilStateConfigs[quadNdx];
604             VkStencilOpState &front                       = depthStencilStateParams.front;
605             VkStencilOpState &back                        = depthStencilStateParams.back;
606 
607             front.compareMask = config.frontReadMask;
608             front.writeMask   = config.frontWriteMask;
609             front.reference   = config.frontRef;
610 
611             back.compareMask = config.backReadMask;
612             back.writeMask   = config.backWriteMask;
613             back.reference   = config.backRef;
614 
615             m_graphicsPipelines[quadNdx]
616                 .setDefaultRasterizerDiscardEnable(!m_colorAttachmentEnable)
617                 .setDefaultMultisampleState()
618                 .setupVertexInputState(&vertexInputStateParams)
619                 .setupPreRasterizationShaderState(viewports, scissors, m_pipelineLayout, *m_renderPass, 0u,
620                                                   m_vertexShaderModule, &rasterizationStateParams)
621                 .setupFragmentShaderState(m_pipelineLayout, *m_renderPass, 0u, m_fragmentShaderModule,
622                                           &depthStencilStateParams)
623                 .setupFragmentOutputState(*m_renderPass, 0,
624                                           (m_colorAttachmentEnable ? &colorBlendStateParams : DE_NULL))
625                 .setMonolithicPipelineLayout(m_pipelineLayout)
626                 .buildPipeline();
627         }
628     }
629 
630     // Create vertex buffer
631     {
632         const VkBufferCreateInfo vertexBufferParams = {
633             VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
634             DE_NULL,                              // const void* pNext;
635             0u,                                   // VkBufferCreateFlags flags;
636             1024u,                                // VkDeviceSize size;
637             VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,    // VkBufferUsageFlags usage;
638             VK_SHARING_MODE_EXCLUSIVE,            // VkSharingMode sharingMode;
639             1u,                                   // uint32_t queueFamilyIndexCount;
640             &queueFamilyIndex                     // const uint32_t* pQueueFamilyIndices;
641         };
642 
643         m_vertices          = createOverlappingQuads();
644         m_vertexBuffer      = createBuffer(vk, vkDevice, &vertexBufferParams);
645         m_vertexBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer),
646                                                 MemoryRequirement::HostVisible);
647 
648         VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(),
649                                      m_vertexBufferAlloc->getOffset()));
650 
651         // Adjust depths
652         for (int quadNdx = 0; quadNdx < 4; quadNdx++)
653             for (int vertexNdx = 0; vertexNdx < 6; vertexNdx++)
654                 m_vertices[quadNdx * 6 + vertexNdx].position.z() = StencilTest::s_quadDepths[quadNdx];
655 
656         // Load vertices into vertex buffer
657         deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBA));
658         flushAlloc(vk, vkDevice, *m_vertexBufferAlloc);
659     }
660 
661     // Create command pool
662     m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
663 
664     // Create command buffer
665     {
666         const VkImageMemoryBarrier colorImageBarrier = {
667             VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,     // VkStructureType            sType;
668             DE_NULL,                                    // const void*                pNext;
669             (VkAccessFlags)0,                           // VkAccessFlags              srcAccessMask;
670             VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,       // VkAccessFlags              dstAccessMask;
671             VK_IMAGE_LAYOUT_UNDEFINED,                  // VkImageLayout              oldLayout;
672             VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,   // VkImageLayout              newLayout;
673             VK_QUEUE_FAMILY_IGNORED,                    // uint32_t                   srcQueueFamilyIndex;
674             VK_QUEUE_FAMILY_IGNORED,                    // uint32_t                   dstQueueFamilyIndex;
675             *m_colorImage,                              // VkImage                    image;
676             {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u} // VkImageSubresourceRange    subresourceRange;
677         };
678 
679         VkImageSubresourceRange stencilImageBarrierSubresourceRange = m_stencilImageSubresourceRange;
680         VkImageLayout newLayout                                     = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
681         if (m_separateDepthStencilLayouts)
682         {
683             stencilImageBarrierSubresourceRange.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
684             newLayout                                      = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL;
685         }
686 
687         const VkImageMemoryBarrier stencilImageBarrier = {
688             VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,       // VkStructureType            sType;
689             DE_NULL,                                      // const void*                pNext;
690             (VkAccessFlags)0,                             // VkAccessFlags              srcAccessMask;
691             VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, // VkAccessFlags              dstAccessMask;
692             VK_IMAGE_LAYOUT_UNDEFINED,                    // VkImageLayout              oldLayout;
693             newLayout,                                    // VkImageLayout              newLayout;
694             VK_QUEUE_FAMILY_IGNORED,                      // uint32_t                   srcQueueFamilyIndex;
695             VK_QUEUE_FAMILY_IGNORED,                      // uint32_t                   dstQueueFamilyIndex;
696             *m_stencilImage,                              // VkImage                    image;
697             stencilImageBarrierSubresourceRange,          // VkImageSubresourceRange    subresourceRange;
698         };
699 
700         std::vector<VkClearValue> attachmentClearValues;
701         std::vector<VkImageMemoryBarrier> imageLayoutBarriers;
702 
703         if (m_colorAttachmentEnable)
704         {
705             attachmentClearValues.push_back(defaultClearValue(m_colorFormat));
706             imageLayoutBarriers.push_back(colorImageBarrier);
707         }
708 
709         attachmentClearValues.push_back(defaultClearValue(m_stencilFormat));
710         imageLayoutBarriers.push_back(stencilImageBarrier);
711 
712         m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
713 
714         beginCommandBuffer(vk, *m_cmdBuffer, 0u);
715 
716         vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
717                               VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
718                                   VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT,
719                               (VkDependencyFlags)0, 0u, DE_NULL, 0u, DE_NULL, (uint32_t)imageLayoutBarriers.size(),
720                               imageLayoutBarriers.data());
721 
722         m_renderPass.begin(vk, *m_cmdBuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()),
723                            (uint32_t)attachmentClearValues.size(), attachmentClearValues.data());
724 
725         const VkDeviceSize quadOffset = (m_vertices.size() / StencilTest::QUAD_COUNT) * sizeof(Vertex4RGBA);
726 
727         for (int quadNdx = 0; quadNdx < StencilTest::QUAD_COUNT; quadNdx++)
728         {
729             VkDeviceSize vertexBufferOffset = quadOffset * quadNdx;
730 
731             m_graphicsPipelines[quadNdx].bind(*m_cmdBuffer);
732             vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
733             vk.cmdDraw(*m_cmdBuffer, (uint32_t)(m_vertices.size() / StencilTest::QUAD_COUNT), 1, 0, 0);
734         }
735 
736         m_renderPass.end(vk, *m_cmdBuffer);
737         endCommandBuffer(vk, *m_cmdBuffer);
738     }
739 }
740 
iterate(void)741 tcu::TestStatus StencilTestInstance::iterate(void)
742 {
743     const DeviceInterface &vk = m_context.getDeviceInterface();
744     const VkDevice vkDevice   = m_context.getDevice();
745     const VkQueue queue       = m_context.getUniversalQueue();
746 
747     submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
748 
749     return verifyImage();
750 }
751 
verifyImage(void)752 tcu::TestStatus StencilTestInstance::verifyImage(void)
753 {
754     const tcu::TextureFormat tcuColorFormat   = mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM);
755     const tcu::TextureFormat tcuStencilFormat = mapVkFormat(m_stencilFormat);
756     const ColorVertexShader vertexShader;
757     const ColorFragmentShader fragmentShader(tcuColorFormat, tcuStencilFormat);
758     const rr::Program program(&vertexShader, &fragmentShader);
759     ReferenceRenderer refRenderer(m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat, tcuStencilFormat, &program);
760     bool colorCompareOk   = false;
761     bool stencilCompareOk = false;
762 
763     // Render reference image
764     {
765         // Set depth state
766         rr::RenderState renderState(refRenderer.getViewportState(),
767                                     m_context.getDeviceProperties().limits.subPixelPrecisionBits);
768 
769         renderState.fragOps.depthTestEnabled   = true;
770         renderState.fragOps.depthFunc          = mapVkCompareOp(VK_COMPARE_OP_LESS);
771         renderState.fragOps.stencilTestEnabled = true;
772 
773         rr::StencilState &refStencilFront = renderState.fragOps.stencilStates[rr::FACETYPE_FRONT];
774         rr::StencilState &refStencilBack  = renderState.fragOps.stencilStates[rr::FACETYPE_BACK];
775 
776         refStencilFront.sFail  = mapVkStencilOp(m_stencilOpStateFront.failOp);
777         refStencilFront.dpFail = mapVkStencilOp(m_stencilOpStateFront.depthFailOp);
778         refStencilFront.dpPass = mapVkStencilOp(m_stencilOpStateFront.passOp);
779         refStencilFront.func   = mapVkCompareOp(m_stencilOpStateFront.compareOp);
780 
781         refStencilBack.sFail  = mapVkStencilOp(m_stencilOpStateBack.failOp);
782         refStencilBack.dpPass = mapVkStencilOp(m_stencilOpStateBack.passOp);
783         refStencilBack.dpFail = mapVkStencilOp(m_stencilOpStateBack.depthFailOp);
784         refStencilBack.func   = mapVkCompareOp(m_stencilOpStateBack.compareOp);
785 
786         // Reverse winding of vertices, as Vulkan screen coordinates start at upper left
787         std::vector<Vertex4RGBA> cwVertices(m_vertices);
788         for (size_t vertexNdx = 0; vertexNdx < cwVertices.size() - 2; vertexNdx += 3)
789         {
790             const Vertex4RGBA cwVertex1 = cwVertices[vertexNdx + 1];
791 
792             cwVertices[vertexNdx + 1] = cwVertices[vertexNdx + 2];
793             cwVertices[vertexNdx + 2] = cwVertex1;
794         }
795 
796         for (int quadNdx = 0; quadNdx < StencilTest::QUAD_COUNT; quadNdx++)
797         {
798             refStencilFront.ref       = (int)StencilTest::s_stencilStateConfigs[quadNdx].frontRef;
799             refStencilFront.compMask  = StencilTest::s_stencilStateConfigs[quadNdx].frontReadMask;
800             refStencilFront.writeMask = StencilTest::s_stencilStateConfigs[quadNdx].frontWriteMask;
801 
802             refStencilBack.ref       = (int)StencilTest::s_stencilStateConfigs[quadNdx].backRef;
803             refStencilBack.compMask  = StencilTest::s_stencilStateConfigs[quadNdx].backReadMask;
804             refStencilBack.writeMask = StencilTest::s_stencilStateConfigs[quadNdx].backWriteMask;
805 
806             refRenderer.draw(
807                 renderState, rr::PRIMITIVETYPE_TRIANGLES,
808                 std::vector<Vertex4RGBA>(cwVertices.begin() + quadNdx * 6, cwVertices.begin() + (quadNdx + 1) * 6));
809         }
810     }
811 
812     // Compare result with reference image
813     if (m_colorAttachmentEnable)
814     {
815         const DeviceInterface &vk       = m_context.getDeviceInterface();
816         const VkDevice vkDevice         = m_context.getDevice();
817         const VkQueue queue             = m_context.getUniversalQueue();
818         const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
819         SimpleAllocator allocator(
820             vk, vkDevice,
821             getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
822         de::UniquePtr<tcu::TextureLevel> result(readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator,
823                                                                     *m_colorImage, m_colorFormat, m_renderSize)
824                                                     .release());
825 
826         colorCompareOk = tcu::intThresholdPositionDeviationCompare(
827             m_context.getTestContext().getLog(), "IntImageCompare", "Image comparison", refRenderer.getAccess(),
828             result->getAccess(), tcu::UVec4(2, 2, 2, 2), tcu::IVec3(1, 1, 0), true, tcu::COMPARE_LOG_RESULT);
829     }
830     else
831     {
832         colorCompareOk = true;
833     }
834 
835     // Compare stencil result with reference image
836     {
837         const DeviceInterface &vk       = m_context.getDeviceInterface();
838         const VkDevice vkDevice         = m_context.getDevice();
839         const VkQueue queue             = m_context.getUniversalQueue();
840         const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
841         SimpleAllocator allocator(
842             vk, vkDevice,
843             getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
844         de::UniquePtr<tcu::TextureLevel> result(readStencilAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator,
845                                                                       *m_stencilImage, m_stencilFormat, m_renderSize)
846                                                     .release());
847 
848         {
849             const tcu::PixelBufferAccess stencilAccess(
850                 tcu::getEffectiveDepthStencilAccess(refRenderer.getDepthStencilAccess(), tcu::Sampler::MODE_STENCIL));
851             stencilCompareOk = tcu::intThresholdPositionDeviationCompare(
852                 m_context.getTestContext().getLog(), "StencilImageCompare", "Stencil image comparison", stencilAccess,
853                 result->getAccess(), tcu::UVec4(2, 2, 2, 2), tcu::IVec3(1, 1, 0), true, tcu::COMPARE_LOG_RESULT);
854         }
855     }
856 
857     if (colorCompareOk && stencilCompareOk)
858         return tcu::TestStatus::pass("Result image matches reference");
859     else
860         return tcu::TestStatus::fail("Image mismatch");
861 }
862 
863 // Utilities for test names
864 
getShortName(VkStencilOp stencilOp)865 const char *getShortName(VkStencilOp stencilOp)
866 {
867     switch (stencilOp)
868     {
869     case VK_STENCIL_OP_KEEP:
870         return "keep";
871     case VK_STENCIL_OP_ZERO:
872         return "zero";
873     case VK_STENCIL_OP_REPLACE:
874         return "repl";
875     case VK_STENCIL_OP_INCREMENT_AND_CLAMP:
876         return "incc";
877     case VK_STENCIL_OP_DECREMENT_AND_CLAMP:
878         return "decc";
879     case VK_STENCIL_OP_INVERT:
880         return "inv";
881     case VK_STENCIL_OP_INCREMENT_AND_WRAP:
882         return "wrap";
883     case VK_STENCIL_OP_DECREMENT_AND_WRAP:
884         return "decw";
885 
886     default:
887         DE_FATAL("Invalid VkStencilOpState value");
888     }
889     return DE_NULL;
890 }
891 
getFormatCaseName(VkFormat format)892 std::string getFormatCaseName(VkFormat format)
893 {
894     const std::string fullName = getFormatName(format);
895 
896     DE_ASSERT(de::beginsWith(fullName, "VK_FORMAT_"));
897 
898     return de::toLower(fullName.substr(10));
899 }
900 
901 } // namespace
902 
createStencilTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType)903 tcu::TestCaseGroup *createStencilTests(tcu::TestContext &testCtx, PipelineConstructionType pipelineConstructionType)
904 {
905     const VkFormat stencilFormats[] = {VK_FORMAT_S8_UINT, VK_FORMAT_D16_UNORM_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT,
906                                        VK_FORMAT_D32_SFLOAT_S8_UINT};
907 
908     DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(compareOps) == 8);
909     DE_STATIC_ASSERT(vk::VK_COMPARE_OP_LAST == 8);
910 
911     static const char *compareOpNames[8] = {"comp_never",
912                                             "comp_less",
913                                             "comp_equal",
914                                             "comp_less_or_equal",
915                                             "comp_greater",
916                                             "comp_not_equal",
917                                             "comp_greater_or_equal",
918                                             "comp_always"};
919 
920     // Stencil tests
921     de::MovePtr<tcu::TestCaseGroup> stencilTests(new tcu::TestCaseGroup(testCtx, "stencil"));
922     // Stencil tests with no color attachment
923     de::MovePtr<tcu::TestCaseGroup> noColorAttachmentTests(new tcu::TestCaseGroup(testCtx, "nocolor"));
924     const bool colorAttachmentEnabled[] = {true, false};
925 
926     for (uint32_t colorAttachmentEnabledIdx = 0; colorAttachmentEnabledIdx < DE_LENGTH_OF_ARRAY(colorAttachmentEnabled);
927          colorAttachmentEnabledIdx++)
928     {
929         const bool colorEnabled = colorAttachmentEnabled[colorAttachmentEnabledIdx];
930         de::MovePtr<tcu::TestCaseGroup> formatTests(new tcu::TestCaseGroup(testCtx, "format"));
931         StencilOpStateUniqueRandomIterator stencilOpItr(123);
932 
933         for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(stencilFormats); formatNdx++)
934         {
935             const VkFormat stencilFormat       = stencilFormats[formatNdx];
936             const bool hasDepth                = tcu::hasDepthComponent(mapVkFormat(stencilFormat).order);
937             const bool hasStencil              = tcu::hasStencilComponent(mapVkFormat(stencilFormat).order);
938             const int separateLayoutsLoopCount = (hasDepth && hasStencil) ? 2 : 1;
939 
940             for (int separateDepthStencilLayouts = 0; separateDepthStencilLayouts < separateLayoutsLoopCount;
941                  ++separateDepthStencilLayouts)
942             {
943                 const bool useSeparateDepthStencilLayouts = bool(separateDepthStencilLayouts);
944 
945                 de::MovePtr<tcu::TestCaseGroup> formatTest(new tcu::TestCaseGroup(
946                     testCtx,
947                     (getFormatCaseName(stencilFormat) + ((useSeparateDepthStencilLayouts) ? "_separate_layouts" : ""))
948                         .c_str()));
949 
950                 de::MovePtr<tcu::TestCaseGroup> stencilStateTests;
951                 {
952                     std::ostringstream desc;
953                     desc << "Draws 4 quads with the following depths and dynamic stencil states: ";
954 
955                     for (int quadNdx = 0; quadNdx < StencilTest::QUAD_COUNT; quadNdx++)
956                     {
957                         const StencilTest::StencilStateConfig &stencilConfig =
958                             StencilTest::s_stencilStateConfigs[quadNdx];
959 
960                         desc << "(" << quadNdx << ") "
961                              << "z = " << StencilTest::s_quadDepths[quadNdx] << ", "
962                              << "frontReadMask = " << stencilConfig.frontReadMask << ", "
963                              << "frontWriteMask = " << stencilConfig.frontWriteMask << ", "
964                              << "frontRef = " << stencilConfig.frontRef << ", "
965                              << "backReadMask = " << stencilConfig.backReadMask << ", "
966                              << "backWriteMask = " << stencilConfig.backWriteMask << ", "
967                              << "backRef = " << stencilConfig.backRef;
968                     }
969 
970                     stencilStateTests = de::MovePtr<tcu::TestCaseGroup>(new tcu::TestCaseGroup(testCtx, "states"));
971                 }
972 
973                 stencilOpItr.reset();
974 
975                 for (uint32_t failOpNdx = 0u; failOpNdx < DE_LENGTH_OF_ARRAY(stencilOps); failOpNdx++)
976                 {
977                     const std::string failOpName = std::string("fail_") + getShortName(stencilOps[failOpNdx]);
978                     de::MovePtr<tcu::TestCaseGroup> failOpTest(new tcu::TestCaseGroup(testCtx, failOpName.c_str()));
979 
980                     for (uint32_t passOpNdx = 0u; passOpNdx < DE_LENGTH_OF_ARRAY(stencilOps); passOpNdx++)
981                     {
982                         const std::string passOpName = std::string("pass_") + getShortName(stencilOps[passOpNdx]);
983                         de::MovePtr<tcu::TestCaseGroup> passOpTest(new tcu::TestCaseGroup(testCtx, passOpName.c_str()));
984 
985                         for (uint32_t dFailOpNdx = 0u; dFailOpNdx < DE_LENGTH_OF_ARRAY(stencilOps); dFailOpNdx++)
986                         {
987                             const std::string dFailOpName =
988                                 std::string("dfail_") + getShortName(stencilOps[dFailOpNdx]);
989                             de::MovePtr<tcu::TestCaseGroup> dFailOpTest(
990                                 new tcu::TestCaseGroup(testCtx, dFailOpName.c_str()));
991 
992                             for (uint32_t compareOpNdx = 0u; compareOpNdx < DE_LENGTH_OF_ARRAY(compareOps);
993                                  compareOpNdx++)
994                             {
995                                 // Iterate front set of stencil state in ascending order
996                                 const VkStencilOpState stencilStateFront = {
997                                     stencilOps[failOpNdx],    // failOp
998                                     stencilOps[passOpNdx],    // passOp
999                                     stencilOps[dFailOpNdx],   // depthFailOp
1000                                     compareOps[compareOpNdx], // compareOp
1001                                     0x0,                      // compareMask
1002                                     0x0,                      // writeMask
1003                                     0x0                       // reference
1004                                 };
1005 
1006                                 // Iterate back set of stencil state in random order
1007                                 const VkStencilOpState stencilStateBack = stencilOpItr.next();
1008                                 const std::string caseName              = compareOpNames[compareOpNdx];
1009 
1010                                 dFailOpTest->addChild(new StencilTest(
1011                                     testCtx, caseName, pipelineConstructionType, stencilFormat, stencilStateFront,
1012                                     stencilStateBack, colorEnabled, useSeparateDepthStencilLayouts));
1013                             }
1014                             passOpTest->addChild(dFailOpTest.release());
1015                         }
1016                         failOpTest->addChild(passOpTest.release());
1017                     }
1018                     stencilStateTests->addChild(failOpTest.release());
1019                 }
1020 
1021                 formatTest->addChild(stencilStateTests.release());
1022                 formatTests->addChild(formatTest.release());
1023             }
1024         }
1025 
1026         if (colorEnabled)
1027             stencilTests->addChild(formatTests.release());
1028         else
1029             noColorAttachmentTests->addChild(formatTests.release());
1030     }
1031 
1032     stencilTests->addChild(noColorAttachmentTests.release());
1033 
1034     return stencilTests.release();
1035 }
1036 
1037 } // namespace pipeline
1038 } // namespace vkt
1039