• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "vktPipelineClearUtil.hpp"
28 #include "vktPipelineImageUtil.hpp"
29 #include "vktPipelineVertexUtil.hpp"
30 #include "vktPipelineReferenceRenderer.hpp"
31 #include "vktPipelineUniqueRandomIterator.hpp"
32 #include "vktTestCase.hpp"
33 #include "vkImageUtil.hpp"
34 #include "vkMemUtil.hpp"
35 #include "vkPrograms.hpp"
36 #include "vkQueryUtil.hpp"
37 #include "vkRef.hpp"
38 #include "vkRefUtil.hpp"
39 #include "vkTypeUtil.hpp"
40 #include "vkCmdUtil.hpp"
41 #include "vkObjUtil.hpp"
42 #include "vkBarrierUtil.hpp"
43 #include "tcuImageCompare.hpp"
44 #include "deMemory.h"
45 #include "deStringUtil.hpp"
46 #include "deUniquePtr.hpp"
47 
48 #include <sstream>
49 #include <vector>
50 
51 namespace vkt
52 {
53 namespace pipeline
54 {
55 
56 using namespace vk;
57 
58 namespace
59 {
60 
isSupportedDepthStencilFormat(const InstanceInterface & instanceInterface,VkPhysicalDevice device,VkFormat format)61 bool isSupportedDepthStencilFormat(const InstanceInterface &instanceInterface, VkPhysicalDevice device, VkFormat format)
62 {
63     VkFormatProperties formatProps;
64 
65     instanceInterface.getPhysicalDeviceFormatProperties(device, format, &formatProps);
66 
67     return (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0;
68 }
69 
70 class StencilOpStateUniqueRandomIterator : public UniqueRandomIterator<VkStencilOpState>
71 {
72 public:
73     StencilOpStateUniqueRandomIterator(int seed);
~StencilOpStateUniqueRandomIterator(void)74     virtual ~StencilOpStateUniqueRandomIterator(void)
75     {
76     }
77     virtual VkStencilOpState getIndexedValue(uint32_t index);
78 
79 private:
80     // Pre-calculated constants
81     const static uint32_t s_stencilOpsLength;
82     const static uint32_t s_stencilOpsLength2;
83     const static uint32_t s_stencilOpsLength3;
84     const static uint32_t s_compareOpsLength;
85 
86     // Total number of cross-combinations of (stencilFailOp x stencilPassOp x stencilDepthFailOp x stencilCompareOp)
87     const static uint32_t s_totalStencilOpStates;
88 };
89 
90 class StencilTest : public vkt::TestCase
91 {
92 public:
93     enum
94     {
95         QUAD_COUNT = 4
96     };
97 
98     struct StencilStateConfig
99     {
100         uint32_t frontReadMask;
101         uint32_t frontWriteMask;
102         uint32_t frontRef;
103 
104         uint32_t backReadMask;
105         uint32_t backWriteMask;
106         uint32_t backRef;
107     };
108 
109     const static StencilStateConfig s_stencilStateConfigs[QUAD_COUNT];
110     const static float s_quadDepths[QUAD_COUNT];
111 
112     StencilTest(tcu::TestContext &testContext, const std::string &name,
113                 PipelineConstructionType pipelineConstructionType, VkFormat stencilFormat,
114                 const VkStencilOpState &stencilOpStateFront, const VkStencilOpState &stencilOpStateBack,
115                 const bool colorAttachmentEnable, const bool separateDepthStencilLayouts);
116     virtual ~StencilTest(void) = default;
117     virtual void initPrograms(SourceCollections &sourceCollections) const;
118     virtual void checkSupport(Context &context) const;
119     virtual TestInstance *createInstance(Context &context) const;
120 
121 private:
122     PipelineConstructionType m_pipelineConstructionType;
123     VkFormat m_stencilFormat;
124     const VkStencilOpState m_stencilOpStateFront;
125     const VkStencilOpState m_stencilOpStateBack;
126     const bool m_colorAttachmentEnable;
127     const bool m_separateDepthStencilLayouts;
128 };
129 
130 class StencilTestInstance : public vkt::TestInstance
131 {
132 public:
133     StencilTestInstance(Context &context, PipelineConstructionType pipelineConstructionType, VkFormat stencilFormat,
134                         const VkStencilOpState &stencilOpStatesFront, const VkStencilOpState &stencilOpStatesBack,
135                         const bool colorAttachmentEnable, const bool separateDepthStencilLayouts);
136     virtual ~StencilTestInstance(void) = default;
137     virtual tcu::TestStatus iterate(void);
138 
139 private:
140     tcu::TestStatus verifyImage(void);
141 
142     VkStencilOpState m_stencilOpStateFront;
143     VkStencilOpState m_stencilOpStateBack;
144     const bool m_colorAttachmentEnable;
145     const bool m_separateDepthStencilLayouts;
146     const tcu::UVec2 m_renderSize;
147     const VkFormat m_colorFormat;
148     const VkFormat m_stencilFormat;
149     VkImageSubresourceRange m_stencilImageSubresourceRange;
150 
151     VkImageCreateInfo m_colorImageCreateInfo;
152     Move<VkImage> m_colorImage;
153     de::MovePtr<Allocation> m_colorImageAlloc;
154     Move<VkImage> m_stencilImage;
155     de::MovePtr<Allocation> m_stencilImageAlloc;
156     Move<VkImageView> m_colorAttachmentView;
157     Move<VkImageView> m_stencilAttachmentView;
158     RenderPassWrapper m_renderPass;
159     Move<VkFramebuffer> m_framebuffer;
160 
161     ShaderWrapper m_vertexShaderModule;
162     ShaderWrapper m_fragmentShaderModule;
163 
164     Move<VkBuffer> m_vertexBuffer;
165     std::vector<Vertex4RGBA> m_vertices;
166     de::MovePtr<Allocation> m_vertexBufferAlloc;
167 
168     PipelineLayoutWrapper m_pipelineLayout;
169     GraphicsPipelineWrapper m_graphicsPipelines[StencilTest::QUAD_COUNT];
170 
171     Move<VkCommandPool> m_cmdPool;
172     Move<VkCommandBuffer> m_cmdBuffer;
173 };
174 
175 const VkStencilOp stencilOps[] = {VK_STENCIL_OP_KEEP,
176                                   VK_STENCIL_OP_ZERO,
177                                   VK_STENCIL_OP_REPLACE,
178                                   VK_STENCIL_OP_INCREMENT_AND_CLAMP,
179                                   VK_STENCIL_OP_DECREMENT_AND_CLAMP,
180                                   VK_STENCIL_OP_INVERT,
181                                   VK_STENCIL_OP_INCREMENT_AND_WRAP,
182                                   VK_STENCIL_OP_DECREMENT_AND_WRAP};
183 
184 const VkCompareOp compareOps[] = {VK_COMPARE_OP_NEVER,
185                                   VK_COMPARE_OP_LESS,
186                                   VK_COMPARE_OP_EQUAL,
187                                   VK_COMPARE_OP_LESS_OR_EQUAL,
188                                   VK_COMPARE_OP_GREATER,
189                                   VK_COMPARE_OP_NOT_EQUAL,
190                                   VK_COMPARE_OP_GREATER_OR_EQUAL,
191                                   VK_COMPARE_OP_ALWAYS};
192 
193 // StencilOpStateUniqueRandomIterator
194 
195 const uint32_t StencilOpStateUniqueRandomIterator::s_stencilOpsLength     = DE_LENGTH_OF_ARRAY(stencilOps);
196 const uint32_t StencilOpStateUniqueRandomIterator::s_stencilOpsLength2    = s_stencilOpsLength * s_stencilOpsLength;
197 const uint32_t StencilOpStateUniqueRandomIterator::s_stencilOpsLength3    = s_stencilOpsLength2 * s_stencilOpsLength;
198 const uint32_t StencilOpStateUniqueRandomIterator::s_compareOpsLength     = DE_LENGTH_OF_ARRAY(compareOps);
199 const uint32_t StencilOpStateUniqueRandomIterator::s_totalStencilOpStates = s_stencilOpsLength3 * s_compareOpsLength;
200 
StencilOpStateUniqueRandomIterator(int seed)201 StencilOpStateUniqueRandomIterator::StencilOpStateUniqueRandomIterator(int seed)
202     : UniqueRandomIterator<VkStencilOpState>(s_totalStencilOpStates, s_totalStencilOpStates, seed)
203 {
204 }
205 
getIndexedValue(uint32_t index)206 VkStencilOpState StencilOpStateUniqueRandomIterator::getIndexedValue(uint32_t index)
207 {
208     const uint32_t stencilCompareOpIndex    = index / s_stencilOpsLength3;
209     const uint32_t stencilCompareOpSeqIndex = stencilCompareOpIndex * s_stencilOpsLength3;
210 
211     const uint32_t stencilDepthFailOpIndex    = (index - stencilCompareOpSeqIndex) / s_stencilOpsLength2;
212     const uint32_t stencilDepthFailOpSeqIndex = stencilDepthFailOpIndex * s_stencilOpsLength2;
213 
214     const uint32_t stencilPassOpIndex =
215         (index - stencilCompareOpSeqIndex - stencilDepthFailOpSeqIndex) / s_stencilOpsLength;
216     const uint32_t stencilPassOpSeqIndex = stencilPassOpIndex * s_stencilOpsLength;
217 
218     const uint32_t stencilFailOpIndex =
219         index - stencilCompareOpSeqIndex - stencilDepthFailOpSeqIndex - stencilPassOpSeqIndex;
220 
221     const VkStencilOpState stencilOpState = {
222         stencilOps[stencilFailOpIndex],      // VkStencilOp failOp;
223         stencilOps[stencilPassOpIndex],      // VkStencilOp passOp;
224         stencilOps[stencilDepthFailOpIndex], // VkStencilOp depthFailOp;
225         compareOps[stencilCompareOpIndex],   // VkCompareOp compareOp;
226         0x0,                                 // uint32_t compareMask;
227         0x0,                                 // uint32_t writeMask;
228         0x0                                  // uint32_t reference;
229     };
230 
231     return stencilOpState;
232 }
233 
234 // StencilTest
235 
236 const StencilTest::StencilStateConfig StencilTest::s_stencilStateConfigs[QUAD_COUNT] = {
237     //    frontReadMask    frontWriteMask        frontRef        backReadMask    backWriteMask    backRef
238     {0xFF, 0xFF, 0xAB, 0xF0, 0xFF, 0xFF},
239     {0xFF, 0xF0, 0xCD, 0xF0, 0xF0, 0xEF},
240     {0xF0, 0x0F, 0xEF, 0xFF, 0x0F, 0xCD},
241     {0xF0, 0x01, 0xFF, 0xFF, 0x01, 0xAB}};
242 
243 const float StencilTest::s_quadDepths[QUAD_COUNT] = {0.1f, 0.0f, 0.3f, 0.2f};
244 
StencilTest(tcu::TestContext & testContext,const std::string & name,PipelineConstructionType pipelineConstructionType,VkFormat stencilFormat,const VkStencilOpState & stencilOpStateFront,const VkStencilOpState & stencilOpStateBack,const bool colorAttachmentEnable,const bool separateDepthStencilLayouts)245 StencilTest::StencilTest(tcu::TestContext &testContext, const std::string &name,
246                          PipelineConstructionType pipelineConstructionType, VkFormat stencilFormat,
247                          const VkStencilOpState &stencilOpStateFront, const VkStencilOpState &stencilOpStateBack,
248                          const bool colorAttachmentEnable, const bool separateDepthStencilLayouts)
249     : vkt::TestCase(testContext, name)
250     , m_pipelineConstructionType(pipelineConstructionType)
251     , m_stencilFormat(stencilFormat)
252     , m_stencilOpStateFront(stencilOpStateFront)
253     , m_stencilOpStateBack(stencilOpStateBack)
254     , m_colorAttachmentEnable(colorAttachmentEnable)
255     , m_separateDepthStencilLayouts(separateDepthStencilLayouts)
256 {
257 }
258 
checkSupport(Context & context) const259 void StencilTest::checkSupport(Context &context) const
260 {
261     if (!isSupportedDepthStencilFormat(context.getInstanceInterface(), context.getPhysicalDevice(), m_stencilFormat))
262         throw tcu::NotSupportedError(std::string("Unsupported depth/stencil format: ") +
263                                      getFormatName(m_stencilFormat));
264 
265     if (m_separateDepthStencilLayouts &&
266         !context.isDeviceFunctionalitySupported("VK_KHR_separate_depth_stencil_layouts"))
267         TCU_THROW(NotSupportedError, "VK_KHR_separate_depth_stencil_layouts is not supported");
268 
269     checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(),
270                                           m_pipelineConstructionType);
271 
272 #ifndef CTS_USES_VULKANSC
273     if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
274         !context.getPortabilitySubsetFeatures().separateStencilMaskRef)
275         TCU_THROW(
276             NotSupportedError,
277             "VK_KHR_portability_subset: Separate stencil mask references are not supported by this implementation");
278 #endif // CTS_USES_VULKANSC
279 }
280 
createInstance(Context & context) const281 TestInstance *StencilTest::createInstance(Context &context) const
282 {
283     return new StencilTestInstance(context, m_pipelineConstructionType, m_stencilFormat, m_stencilOpStateFront,
284                                    m_stencilOpStateBack, m_colorAttachmentEnable, m_separateDepthStencilLayouts);
285 }
286 
initPrograms(SourceCollections & sourceCollections) const287 void StencilTest::initPrograms(SourceCollections &sourceCollections) const
288 {
289     if (m_colorAttachmentEnable)
290     {
291         sourceCollections.glslSources.add("color_vert")
292             << glu::VertexSource("#version 310 es\n"
293                                  "layout(location = 0) in vec4 position;\n"
294                                  "layout(location = 1) in vec4 color;\n"
295                                  "layout(location = 0) out highp vec4 vtxColor;\n"
296                                  "void main (void)\n"
297                                  "{\n"
298                                  "    gl_Position = position;\n"
299                                  "    vtxColor = color;\n"
300                                  "}\n");
301 
302         sourceCollections.glslSources.add("color_frag")
303             << glu::FragmentSource("#version 310 es\n"
304                                    "layout(location = 0) in highp vec4 vtxColor;\n"
305                                    "layout(location = 0) out highp vec4 fragColor;\n"
306                                    "void main (void)\n"
307                                    "{\n"
308                                    "    fragColor = vtxColor;\n"
309                                    "}\n");
310     }
311     else
312     {
313         sourceCollections.glslSources.add("color_vert") << glu::VertexSource("#version 310 es\n"
314                                                                              "layout(location = 0) in vec4 position;\n"
315                                                                              "layout(location = 1) in vec4 color;\n"
316                                                                              "void main (void)\n"
317                                                                              "{\n"
318                                                                              "    gl_Position = position;\n"
319                                                                              "}\n");
320     }
321 }
322 
323 // StencilTestInstance
324 
StencilTestInstance(Context & context,PipelineConstructionType pipelineConstructionType,VkFormat stencilFormat,const VkStencilOpState & stencilOpStateFront,const VkStencilOpState & stencilOpStateBack,const bool colorAttachmentEnable,const bool separateDepthStencilLayouts)325 StencilTestInstance::StencilTestInstance(Context &context, PipelineConstructionType pipelineConstructionType,
326                                          VkFormat stencilFormat, const VkStencilOpState &stencilOpStateFront,
327                                          const VkStencilOpState &stencilOpStateBack, const bool colorAttachmentEnable,
328                                          const bool separateDepthStencilLayouts)
329     : vkt::TestInstance(context)
330     , m_stencilOpStateFront(stencilOpStateFront)
331     , m_stencilOpStateBack(stencilOpStateBack)
332     , m_colorAttachmentEnable(colorAttachmentEnable)
333     , m_separateDepthStencilLayouts(separateDepthStencilLayouts)
334     , m_renderSize(32, 32)
335     , m_colorFormat(colorAttachmentEnable ? VK_FORMAT_R8G8B8A8_UNORM : VK_FORMAT_UNDEFINED)
336     , m_stencilFormat(stencilFormat)
337     , m_graphicsPipelines{{context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(),
338                            context.getDevice(), context.getDeviceExtensions(), pipelineConstructionType},
339                           {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 {
346     const DeviceInterface &vk       = context.getDeviceInterface();
347     const VkDevice vkDevice         = context.getDevice();
348     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
349     SimpleAllocator memAlloc(
350         vk, vkDevice, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()));
351     const VkComponentMapping componentMappingRGBA = {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G,
352                                                      VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A};
353 
354     // Create color image
355     if (m_colorAttachmentEnable)
356     {
357         const VkImageCreateInfo colorImageParams = {
358             VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                                   // VkStructureType sType;
359             nullptr,                                                               // const void* pNext;
360             0u,                                                                    // VkImageCreateFlags flags;
361             VK_IMAGE_TYPE_2D,                                                      // VkImageType imageType;
362             m_colorFormat,                                                         // VkFormat format;
363             {m_renderSize.x(), m_renderSize.y(), 1u},                              // VkExtent3D extent;
364             1u,                                                                    // uint32_t mipLevels;
365             1u,                                                                    // uint32_t arrayLayers;
366             VK_SAMPLE_COUNT_1_BIT,                                                 // VkSampleCountFlagBits samples;
367             VK_IMAGE_TILING_OPTIMAL,                                               // VkImageTiling tiling;
368             VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage;
369             VK_SHARING_MODE_EXCLUSIVE,                                             // VkSharingMode sharingMode;
370             1u,                                                                    // uint32_t queueFamilyIndexCount;
371             &queueFamilyIndex,        // const uint32_t* pQueueFamilyIndices;
372             VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
373         };
374 
375         m_colorImageCreateInfo = colorImageParams;
376         m_colorImage           = createImage(vk, vkDevice, &m_colorImageCreateInfo);
377 
378         // Allocate and bind color image memory
379         m_colorImageAlloc =
380             memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any);
381         VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(),
382                                     m_colorImageAlloc->getOffset()));
383     }
384 
385     // Create stencil image
386     {
387         const VkImageUsageFlags usageFlags =
388             VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
389 
390         const VkImageCreateInfo stencilImageParams = {
391             VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,      // VkStructureType sType;
392             nullptr,                                  // const void* pNext;
393             0u,                                       // VkImageCreateFlags flags;
394             VK_IMAGE_TYPE_2D,                         // VkImageType imageType;
395             m_stencilFormat,                          // VkFormat format;
396             {m_renderSize.x(), m_renderSize.y(), 1u}, // VkExtent3D extent;
397             1u,                                       // uint32_t mipLevels;
398             1u,                                       // uint32_t arrayLayers;
399             VK_SAMPLE_COUNT_1_BIT,                    // VkSampleCountFlagBits samples;
400             VK_IMAGE_TILING_OPTIMAL,                  // VkImageTiling tiling;
401             usageFlags,                               // VkImageUsageFlags usage;
402             VK_SHARING_MODE_EXCLUSIVE,                // VkSharingMode sharingMode;
403             1u,                                       // uint32_t queueFamilyIndexCount;
404             &queueFamilyIndex,                        // const uint32_t* pQueueFamilyIndices;
405             VK_IMAGE_LAYOUT_UNDEFINED                 // VkImageLayout initialLayout;
406         };
407 
408         m_stencilImage = createImage(vk, vkDevice, &stencilImageParams);
409 
410         // Allocate and bind stencil image memory
411         m_stencilImageAlloc =
412             memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_stencilImage), MemoryRequirement::Any);
413         VK_CHECK(vk.bindImageMemory(vkDevice, *m_stencilImage, m_stencilImageAlloc->getMemory(),
414                                     m_stencilImageAlloc->getOffset()));
415 
416         const VkImageAspectFlags aspect = (mapVkFormat(m_stencilFormat).order == tcu::TextureFormat::DS ?
417                                                VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_DEPTH_BIT :
418                                                VK_IMAGE_ASPECT_STENCIL_BIT);
419         m_stencilImageSubresourceRange =
420             makeImageSubresourceRange(aspect, 0u, stencilImageParams.mipLevels, 0u, stencilImageParams.arrayLayers);
421     }
422 
423     // Create color attachment view
424     if (m_colorAttachmentEnable)
425     {
426         const VkImageViewCreateInfo colorAttachmentViewParams = {
427             VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,   // VkStructureType sType;
428             nullptr,                                    // const void* pNext;
429             0u,                                         // VkImageViewCreateFlags flags;
430             *m_colorImage,                              // VkImage image;
431             VK_IMAGE_VIEW_TYPE_2D,                      // VkImageViewType viewType;
432             m_colorFormat,                              // VkFormat format;
433             componentMappingRGBA,                       // VkComponentMapping components;
434             {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u} // VkImageSubresourceRange subresourceRange;
435         };
436 
437         m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams);
438     }
439 
440     // Create stencil attachment view
441     {
442         const VkImageViewCreateInfo stencilAttachmentViewParams = {
443             VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
444             nullptr,                                  // const void* pNext;
445             0u,                                       // VkImageViewCreateFlags flags;
446             *m_stencilImage,                          // VkImage image;
447             VK_IMAGE_VIEW_TYPE_2D,                    // VkImageViewType viewType;
448             m_stencilFormat,                          // VkFormat format;
449             componentMappingRGBA,                     // VkComponentMapping components;
450             m_stencilImageSubresourceRange,           // VkImageSubresourceRange subresourceRange;
451         };
452 
453         m_stencilAttachmentView = createImageView(vk, vkDevice, &stencilAttachmentViewParams);
454     }
455 
456     // Create render pass
457     m_renderPass = RenderPassWrapper(pipelineConstructionType, vk, vkDevice, m_colorFormat, m_stencilFormat);
458 
459     // Create framebuffer
460     {
461         std::vector<VkImage> images;
462         std::vector<VkImageView> attachmentBindInfos;
463 
464         if (m_colorAttachmentEnable)
465         {
466             images.push_back(*m_colorImage);
467             attachmentBindInfos.push_back(*m_colorAttachmentView);
468         }
469 
470         images.push_back(*m_stencilImage);
471         attachmentBindInfos.push_back(*m_stencilAttachmentView);
472 
473         const VkFramebufferCreateInfo framebufferParams = {
474             VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
475             nullptr,                                   // const void* pNext;
476             0u,                                        // VkFramebufferCreateFlags flags;
477             *m_renderPass,                             // VkRenderPass renderPass;
478             (uint32_t)attachmentBindInfos.size(),      // uint32_t attachmentCount;
479             attachmentBindInfos.data(),                // const VkImageView* pAttachments;
480             (uint32_t)m_renderSize.x(),                // uint32_t width;
481             (uint32_t)m_renderSize.y(),                // uint32_t height;
482             1u                                         // uint32_t layers;
483         };
484 
485         m_renderPass.createFramebuffer(vk, vkDevice, &framebufferParams, images);
486     }
487 
488     // Create pipeline layout
489     {
490         const VkPipelineLayoutCreateInfo pipelineLayoutParams = {
491             VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
492             nullptr,                                       // const void* pNext;
493             0u,                                            // VkPipelineLayoutCreateFlags flags;
494             0u,                                            // uint32_t setLayoutCount;
495             nullptr,                                       // const VkDescriptorSetLayout* pSetLayouts;
496             0u,                                            // uint32_t pushConstantRangeCount;
497             nullptr                                        // const VkPushConstantRange* pPushConstantRanges;
498         };
499 
500         m_pipelineLayout = PipelineLayoutWrapper(pipelineConstructionType, vk, vkDevice, &pipelineLayoutParams);
501     }
502 
503     m_vertexShaderModule = ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("color_vert"), 0);
504     if (m_colorAttachmentEnable)
505         m_fragmentShaderModule = ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("color_frag"), 0);
506 
507     // Create pipeline
508     {
509         const VkVertexInputBindingDescription vertexInputBindingDescription{
510             0u,                         // uint32_t binding;
511             sizeof(Vertex4RGBA),        // uint32_t strideInBytes;
512             VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputStepRate inputRate;
513         };
514 
515         const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2]{
516             {
517                 0u,                            // uint32_t location;
518                 0u,                            // uint32_t binding;
519                 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
520                 0u                             // uint32_t offsetInBytes;
521             },
522             {
523                 1u,                            // uint32_t location;
524                 0u,                            // uint32_t binding;
525                 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
526                 offsetof(Vertex4RGBA, color),  // uint32_t offsetInBytes;
527             }};
528 
529         const VkPipelineVertexInputStateCreateInfo vertexInputStateParams{
530             VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
531             nullptr,                                                   // const void* pNext;
532             0u,                                                        // VkPipelineVertexInputStateCreateFlags flags;
533             1u,                                                        // uint32_t vertexBindingDescriptionCount;
534             &vertexInputBindingDescription,  // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
535             2u,                              // uint32_t vertexAttributeDescriptionCount;
536             vertexInputAttributeDescriptions // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
537         };
538 
539         const std::vector<VkViewport> viewports{makeViewport(m_renderSize)};
540         const std::vector<VkRect2D> scissors{makeRect2D(m_renderSize)};
541 
542         const bool isDepthEnabled = (vk::mapVkFormat(m_stencilFormat).order != tcu::TextureFormat::S);
543 
544         VkPipelineDepthStencilStateCreateInfo depthStencilStateParams{
545             VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
546             nullptr,                                                    // const void* pNext;
547             0u,                                                         // VkPipelineDepthStencilStateCreateFlags flags;
548             isDepthEnabled,                                             // VkBool32 depthTestEnable;
549             isDepthEnabled,                                             // VkBool32 depthWriteEnable;
550             VK_COMPARE_OP_LESS,                                         // VkCompareOp depthCompareOp;
551             false,                                                      // VkBool32 depthBoundsTestEnable;
552             true,                                                       // VkBool32 stencilTestEnable;
553             m_stencilOpStateFront,                                      // VkStencilOpState front;
554             m_stencilOpStateBack,                                       // VkStencilOpState back;
555             0.0f,                                                       // float minDepthBounds;
556             1.0f                                                        // float maxDepthBounds;
557         };
558 
559         // Make sure rasterization is not disabled when the fragment shader is missing.
560         const vk::VkPipelineRasterizationStateCreateInfo rasterizationStateParams{
561             vk::VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
562             nullptr,                                                        // const void* pNext;
563             0u,                                  // VkPipelineRasterizationStateCreateFlags flags;
564             VK_FALSE,                            // VkBool32 depthClampEnable;
565             VK_FALSE,                            // VkBool32 rasterizerDiscardEnable;
566             vk::VK_POLYGON_MODE_FILL,            // VkPolygonMode polygonMode;
567             vk::VK_CULL_MODE_NONE,               // VkCullModeFlags cullMode;
568             vk::VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
569             VK_FALSE,                            // VkBool32 depthBiasEnable;
570             0.0f,                                // float depthBiasConstantFactor;
571             0.0f,                                // float depthBiasClamp;
572             0.0f,                                // float depthBiasSlopeFactor;
573             1.0f,                                // float lineWidth;
574         };
575 
576         const vk::VkPipelineColorBlendAttachmentState blendState{
577             VK_FALSE,
578             VK_BLEND_FACTOR_ONE,
579             VK_BLEND_FACTOR_ONE,
580             VK_BLEND_OP_ADD,
581             VK_BLEND_FACTOR_ONE,
582             VK_BLEND_FACTOR_ONE,
583             VK_BLEND_OP_ADD,
584             VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT,
585 
586         };
587         const vk::VkPipelineColorBlendStateCreateInfo colorBlendStateParams{
588             vk::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType                                sType
589             nullptr,                           // const void*                                    pNext
590             0u,                                // VkPipelineColorBlendStateCreateFlags            flags
591             VK_FALSE,                          // VkBool32                                        logicOpEnable
592             vk::VK_LOGIC_OP_CLEAR,             // VkLogicOp                                    logicOp
593             m_colorAttachmentEnable ? 1u : 0u, // uint32_t                                        attachmentCount
594             &blendState,                       // const VkPipelineColorBlendAttachmentState*    pAttachments
595             {1.0f, 1.0f, 1.0f, 1.0f}           // float                                        blendConstants[4]
596         };
597 
598         // Setup different stencil masks and refs in each quad
599         for (int quadNdx = 0; quadNdx < StencilTest::QUAD_COUNT; quadNdx++)
600         {
601             const StencilTest::StencilStateConfig &config = StencilTest::s_stencilStateConfigs[quadNdx];
602             VkStencilOpState &front                       = depthStencilStateParams.front;
603             VkStencilOpState &back                        = depthStencilStateParams.back;
604 
605             front.compareMask = config.frontReadMask;
606             front.writeMask   = config.frontWriteMask;
607             front.reference   = config.frontRef;
608 
609             back.compareMask = config.backReadMask;
610             back.writeMask   = config.backWriteMask;
611             back.reference   = config.backRef;
612 
613             m_graphicsPipelines[quadNdx]
614                 .setDefaultRasterizerDiscardEnable(!m_colorAttachmentEnable)
615                 .setDefaultMultisampleState()
616                 .setupVertexInputState(&vertexInputStateParams)
617                 .setupPreRasterizationShaderState(viewports, scissors, m_pipelineLayout, *m_renderPass, 0u,
618                                                   m_vertexShaderModule, &rasterizationStateParams)
619                 .setupFragmentShaderState(m_pipelineLayout, *m_renderPass, 0u, m_fragmentShaderModule,
620                                           &depthStencilStateParams)
621                 .setupFragmentOutputState(*m_renderPass, 0,
622                                           (m_colorAttachmentEnable ? &colorBlendStateParams : nullptr))
623                 .setMonolithicPipelineLayout(m_pipelineLayout)
624                 .buildPipeline();
625         }
626     }
627 
628     // Create vertex buffer
629     {
630         const VkBufferCreateInfo vertexBufferParams = {
631             VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
632             nullptr,                              // const void* pNext;
633             0u,                                   // VkBufferCreateFlags flags;
634             1024u,                                // VkDeviceSize size;
635             VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,    // VkBufferUsageFlags usage;
636             VK_SHARING_MODE_EXCLUSIVE,            // VkSharingMode sharingMode;
637             1u,                                   // uint32_t queueFamilyIndexCount;
638             &queueFamilyIndex                     // const uint32_t* pQueueFamilyIndices;
639         };
640 
641         m_vertices          = createOverlappingQuads();
642         m_vertexBuffer      = createBuffer(vk, vkDevice, &vertexBufferParams);
643         m_vertexBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer),
644                                                 MemoryRequirement::HostVisible);
645 
646         VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(),
647                                      m_vertexBufferAlloc->getOffset()));
648 
649         // Adjust depths
650         for (int quadNdx = 0; quadNdx < 4; quadNdx++)
651             for (int vertexNdx = 0; vertexNdx < 6; vertexNdx++)
652                 m_vertices[quadNdx * 6 + vertexNdx].position.z() = StencilTest::s_quadDepths[quadNdx];
653 
654         // Load vertices into vertex buffer
655         deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBA));
656         flushAlloc(vk, vkDevice, *m_vertexBufferAlloc);
657     }
658 
659     // Create command pool
660     m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
661 
662     // Create command buffer
663     {
664         const VkImageMemoryBarrier colorImageBarrier = {
665             VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,     // VkStructureType            sType;
666             nullptr,                                    // const void*                pNext;
667             (VkAccessFlags)0,                           // VkAccessFlags              srcAccessMask;
668             VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,       // VkAccessFlags              dstAccessMask;
669             VK_IMAGE_LAYOUT_UNDEFINED,                  // VkImageLayout              oldLayout;
670             VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,   // VkImageLayout              newLayout;
671             VK_QUEUE_FAMILY_IGNORED,                    // uint32_t                   srcQueueFamilyIndex;
672             VK_QUEUE_FAMILY_IGNORED,                    // uint32_t                   dstQueueFamilyIndex;
673             *m_colorImage,                              // VkImage                    image;
674             {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u} // VkImageSubresourceRange    subresourceRange;
675         };
676 
677         VkImageSubresourceRange stencilImageBarrierSubresourceRange = m_stencilImageSubresourceRange;
678         VkImageLayout newLayout                                     = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
679         if (m_separateDepthStencilLayouts)
680         {
681             stencilImageBarrierSubresourceRange.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
682             newLayout                                      = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL;
683         }
684 
685         const VkImageMemoryBarrier stencilImageBarrier = {
686             VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,       // VkStructureType            sType;
687             nullptr,                                      // const void*                pNext;
688             (VkAccessFlags)0,                             // VkAccessFlags              srcAccessMask;
689             VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, // VkAccessFlags              dstAccessMask;
690             VK_IMAGE_LAYOUT_UNDEFINED,                    // VkImageLayout              oldLayout;
691             newLayout,                                    // VkImageLayout              newLayout;
692             VK_QUEUE_FAMILY_IGNORED,                      // uint32_t                   srcQueueFamilyIndex;
693             VK_QUEUE_FAMILY_IGNORED,                      // uint32_t                   dstQueueFamilyIndex;
694             *m_stencilImage,                              // VkImage                    image;
695             stencilImageBarrierSubresourceRange,          // VkImageSubresourceRange    subresourceRange;
696         };
697 
698         std::vector<VkClearValue> attachmentClearValues;
699         std::vector<VkImageMemoryBarrier> imageLayoutBarriers;
700 
701         if (m_colorAttachmentEnable)
702         {
703             attachmentClearValues.push_back(defaultClearValue(m_colorFormat));
704             imageLayoutBarriers.push_back(colorImageBarrier);
705         }
706 
707         attachmentClearValues.push_back(defaultClearValue(m_stencilFormat));
708         imageLayoutBarriers.push_back(stencilImageBarrier);
709 
710         m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
711 
712         beginCommandBuffer(vk, *m_cmdBuffer, 0u);
713 
714         vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
715                               VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
716                                   VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT,
717                               (VkDependencyFlags)0, 0u, nullptr, 0u, nullptr, (uint32_t)imageLayoutBarriers.size(),
718                               imageLayoutBarriers.data());
719 
720         m_renderPass.begin(vk, *m_cmdBuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()),
721                            (uint32_t)attachmentClearValues.size(), attachmentClearValues.data());
722 
723         const VkDeviceSize quadOffset = (m_vertices.size() / StencilTest::QUAD_COUNT) * sizeof(Vertex4RGBA);
724 
725         for (int quadNdx = 0; quadNdx < StencilTest::QUAD_COUNT; quadNdx++)
726         {
727             VkDeviceSize vertexBufferOffset = quadOffset * quadNdx;
728 
729             m_graphicsPipelines[quadNdx].bind(*m_cmdBuffer);
730             vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
731             vk.cmdDraw(*m_cmdBuffer, (uint32_t)(m_vertices.size() / StencilTest::QUAD_COUNT), 1, 0, 0);
732         }
733 
734         m_renderPass.end(vk, *m_cmdBuffer);
735         endCommandBuffer(vk, *m_cmdBuffer);
736     }
737 }
738 
iterate(void)739 tcu::TestStatus StencilTestInstance::iterate(void)
740 {
741     const DeviceInterface &vk = m_context.getDeviceInterface();
742     const VkDevice vkDevice   = m_context.getDevice();
743     const VkQueue queue       = m_context.getUniversalQueue();
744 
745     submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
746 
747     return verifyImage();
748 }
749 
verifyImage(void)750 tcu::TestStatus StencilTestInstance::verifyImage(void)
751 {
752     const tcu::TextureFormat tcuColorFormat   = mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM);
753     const tcu::TextureFormat tcuStencilFormat = mapVkFormat(m_stencilFormat);
754     const ColorVertexShader vertexShader;
755     const ColorFragmentShader fragmentShader(tcuColorFormat, tcuStencilFormat);
756     const rr::Program program(&vertexShader, &fragmentShader);
757     ReferenceRenderer refRenderer(m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat, tcuStencilFormat, &program);
758     bool colorCompareOk   = false;
759     bool stencilCompareOk = false;
760 
761     // Render reference image
762     {
763         // Set depth state
764         rr::RenderState renderState(refRenderer.getViewportState(),
765                                     m_context.getDeviceProperties().limits.subPixelPrecisionBits);
766 
767         renderState.fragOps.depthTestEnabled   = true;
768         renderState.fragOps.depthFunc          = mapVkCompareOp(VK_COMPARE_OP_LESS);
769         renderState.fragOps.stencilTestEnabled = true;
770 
771         rr::StencilState &refStencilFront = renderState.fragOps.stencilStates[rr::FACETYPE_FRONT];
772         rr::StencilState &refStencilBack  = renderState.fragOps.stencilStates[rr::FACETYPE_BACK];
773 
774         refStencilFront.sFail  = mapVkStencilOp(m_stencilOpStateFront.failOp);
775         refStencilFront.dpFail = mapVkStencilOp(m_stencilOpStateFront.depthFailOp);
776         refStencilFront.dpPass = mapVkStencilOp(m_stencilOpStateFront.passOp);
777         refStencilFront.func   = mapVkCompareOp(m_stencilOpStateFront.compareOp);
778 
779         refStencilBack.sFail  = mapVkStencilOp(m_stencilOpStateBack.failOp);
780         refStencilBack.dpPass = mapVkStencilOp(m_stencilOpStateBack.passOp);
781         refStencilBack.dpFail = mapVkStencilOp(m_stencilOpStateBack.depthFailOp);
782         refStencilBack.func   = mapVkCompareOp(m_stencilOpStateBack.compareOp);
783 
784         // Reverse winding of vertices, as Vulkan screen coordinates start at upper left
785         std::vector<Vertex4RGBA> cwVertices(m_vertices);
786         for (size_t vertexNdx = 0; vertexNdx < cwVertices.size() - 2; vertexNdx += 3)
787         {
788             const Vertex4RGBA cwVertex1 = cwVertices[vertexNdx + 1];
789 
790             cwVertices[vertexNdx + 1] = cwVertices[vertexNdx + 2];
791             cwVertices[vertexNdx + 2] = cwVertex1;
792         }
793 
794         for (int quadNdx = 0; quadNdx < StencilTest::QUAD_COUNT; quadNdx++)
795         {
796             refStencilFront.ref       = (int)StencilTest::s_stencilStateConfigs[quadNdx].frontRef;
797             refStencilFront.compMask  = StencilTest::s_stencilStateConfigs[quadNdx].frontReadMask;
798             refStencilFront.writeMask = StencilTest::s_stencilStateConfigs[quadNdx].frontWriteMask;
799 
800             refStencilBack.ref       = (int)StencilTest::s_stencilStateConfigs[quadNdx].backRef;
801             refStencilBack.compMask  = StencilTest::s_stencilStateConfigs[quadNdx].backReadMask;
802             refStencilBack.writeMask = StencilTest::s_stencilStateConfigs[quadNdx].backWriteMask;
803 
804             refRenderer.draw(
805                 renderState, rr::PRIMITIVETYPE_TRIANGLES,
806                 std::vector<Vertex4RGBA>(cwVertices.begin() + quadNdx * 6, cwVertices.begin() + (quadNdx + 1) * 6));
807         }
808     }
809 
810     // Compare result with reference image
811     if (m_colorAttachmentEnable)
812     {
813         const DeviceInterface &vk       = m_context.getDeviceInterface();
814         const VkDevice vkDevice         = m_context.getDevice();
815         const VkQueue queue             = m_context.getUniversalQueue();
816         const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
817         SimpleAllocator allocator(
818             vk, vkDevice,
819             getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
820         de::UniquePtr<tcu::TextureLevel> result(readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator,
821                                                                     *m_colorImage, m_colorFormat, m_renderSize)
822                                                     .release());
823 
824         colorCompareOk = tcu::intThresholdPositionDeviationCompare(
825             m_context.getTestContext().getLog(), "IntImageCompare", "Image comparison", refRenderer.getAccess(),
826             result->getAccess(), tcu::UVec4(2, 2, 2, 2), tcu::IVec3(1, 1, 0), true, tcu::COMPARE_LOG_RESULT);
827     }
828     else
829     {
830         colorCompareOk = true;
831     }
832 
833     // Compare stencil result with reference image
834     {
835         const DeviceInterface &vk       = m_context.getDeviceInterface();
836         const VkDevice vkDevice         = m_context.getDevice();
837         const VkQueue queue             = m_context.getUniversalQueue();
838         const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
839         SimpleAllocator allocator(
840             vk, vkDevice,
841             getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
842         de::UniquePtr<tcu::TextureLevel> result(readStencilAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator,
843                                                                       *m_stencilImage, m_stencilFormat, m_renderSize)
844                                                     .release());
845 
846         {
847             const tcu::PixelBufferAccess stencilAccess(
848                 tcu::getEffectiveDepthStencilAccess(refRenderer.getDepthStencilAccess(), tcu::Sampler::MODE_STENCIL));
849             stencilCompareOk = tcu::intThresholdPositionDeviationCompare(
850                 m_context.getTestContext().getLog(), "StencilImageCompare", "Stencil image comparison", stencilAccess,
851                 result->getAccess(), tcu::UVec4(2, 2, 2, 2), tcu::IVec3(1, 1, 0), true, tcu::COMPARE_LOG_RESULT);
852         }
853     }
854 
855     if (colorCompareOk && stencilCompareOk)
856         return tcu::TestStatus::pass("Result image matches reference");
857     else
858         return tcu::TestStatus::fail("Image mismatch");
859 }
860 
861 struct NoStencilAttachmentParams
862 {
863     PipelineConstructionType pipelineConstructionType;
864     VkFormat format;
865     bool dynamicRendering;
866     bool dynamicEnable;
867 
useDynamicRenderingvkt::pipeline::__anon7d94880a0111::NoStencilAttachmentParams868     bool useDynamicRendering(void) const
869     {
870         return (dynamicRendering || isConstructionTypeShaderObject(pipelineConstructionType));
871     }
872 };
873 
874 class NoStencilAttachmentCase : public vkt::TestCase
875 {
876 public:
NoStencilAttachmentCase(tcu::TestContext & testCtx,const std::string & name,const NoStencilAttachmentParams & params)877     NoStencilAttachmentCase(tcu::TestContext &testCtx, const std::string &name, const NoStencilAttachmentParams &params)
878         : vkt::TestCase(testCtx, name)
879         , m_params(params)
880     {
881     }
~NoStencilAttachmentCase(void)882     virtual ~NoStencilAttachmentCase(void)
883     {
884     }
885 
886     void checkSupport(Context &context) const override;
887     void initPrograms(vk::SourceCollections &programCollection) const override;
888     TestInstance *createInstance(Context &context) const override;
889 
890     static void getImageCreateInfo(VkImageCreateInfo *createInfo, const VkFormat format);
891     static tcu::Vec4 getClearColor(void);
892     static tcu::Vec4 getGeometryColor(void);
893 
894 protected:
895     const NoStencilAttachmentParams m_params;
896 };
897 
898 class NoStencilAttachmentInstance : public vkt::TestInstance
899 {
900 public:
NoStencilAttachmentInstance(Context & context,const NoStencilAttachmentParams & params)901     NoStencilAttachmentInstance(Context &context, const NoStencilAttachmentParams &params)
902         : vkt::TestInstance(context)
903         , m_params(params)
904     {
905     }
~NoStencilAttachmentInstance(void)906     virtual ~NoStencilAttachmentInstance(void)
907     {
908     }
909 
910     tcu::TestStatus iterate(void) override;
911 
912 protected:
913     const NoStencilAttachmentParams m_params;
914 };
915 
getImageCreateInfo(VkImageCreateInfo * createInfo_,const VkFormat format)916 void NoStencilAttachmentCase::getImageCreateInfo(VkImageCreateInfo *createInfo_, const VkFormat format)
917 {
918     const VkImageUsageFlags mainUsage = (isDepthStencilFormat(format) ? VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT :
919                                                                         VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
920     const VkImageUsageFlags usage     = (mainUsage | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
921 
922     *createInfo_ = {
923         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
924         nullptr,                             // const void* pNext;
925         0u,                                  // VkImageCreateFlags flags;
926         VK_IMAGE_TYPE_2D,                    // VkImageType imageType;
927         format,                              // VkFormat format;
928         makeExtent3D(32u, 32u, 1u),          // VkExtent3D extent;
929         1u,                                  // uint32_t mipLevels;
930         1u,                                  // uint32_t arrayLayers;
931         VK_SAMPLE_COUNT_1_BIT,               // VkSampleCountFlagBits samples;
932         VK_IMAGE_TILING_OPTIMAL,             // VkImageTiling tiling;
933         usage,                               // VkImageUsageFlags usage;
934         VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode sharingMode;
935         0u,                                  // uint32_t queueFamilyIndexCount;
936         nullptr,                             // const uint32_t* pQueueFamilyIndices;
937         VK_IMAGE_LAYOUT_UNDEFINED,           // VkImageLayout initialLayout;
938     };
939 }
940 
getClearColor(void)941 tcu::Vec4 NoStencilAttachmentCase::getClearColor(void)
942 {
943     return tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
944 }
945 
getGeometryColor(void)946 tcu::Vec4 NoStencilAttachmentCase::getGeometryColor(void)
947 {
948     return tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f);
949 }
950 
checkSupport(Context & context) const951 void NoStencilAttachmentCase::checkSupport(Context &context) const
952 {
953     const auto &vki           = context.getInstanceInterface();
954     const auto physicalDevice = context.getPhysicalDevice();
955 
956     checkPipelineConstructionRequirements(vki, physicalDevice, m_params.pipelineConstructionType);
957 
958     if (m_params.dynamicRendering)
959         context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
960 
961     if (m_params.dynamicEnable && !isConstructionTypeShaderObject(m_params.pipelineConstructionType))
962         context.requireDeviceFunctionality("VK_EXT_extended_dynamic_state");
963 
964     VkImageCreateInfo createInfo;
965     VkImageFormatProperties imgFormatProperties;
966 
967     getImageCreateInfo(&createInfo, m_params.format);
968 
969     const auto result = vki.getPhysicalDeviceImageFormatProperties(
970         physicalDevice, createInfo.format, createInfo.imageType, createInfo.tiling, createInfo.usage, createInfo.flags,
971         &imgFormatProperties);
972 
973     if (result == VK_ERROR_FORMAT_NOT_SUPPORTED)
974         TCU_THROW(NotSupportedError, "Format does not support the required features");
975 
976     VK_CHECK(result);
977 }
978 
initPrograms(SourceCollections & dst) const979 void NoStencilAttachmentCase::initPrograms(SourceCollections &dst) const
980 {
981     std::ostringstream vert;
982     vert << "#version 460\n"
983          << "vec2 positions[3] = vec2[](\n"
984          << "    vec2(-1.0, -1.0),\n"
985          << "    vec2( 3.0, -1.0),\n"
986          << "    vec2(-1.0,  3.0)\n"
987          << ");\n"
988          << "layout (push_constant, std430) uniform PushConstantBlock {\n"
989          << "    float depth;\n"
990          << "} pc;\n"
991          << "void main (void) {\n"
992          << "    gl_Position = vec4(positions[gl_VertexIndex % 3], pc.depth, 1.0);\n"
993          << "}\n";
994     dst.glslSources.add("vert") << glu::VertexSource(vert.str());
995 
996     std::ostringstream frag;
997     frag << "#version 460\n"
998          << "layout (location=0) out vec4 outColor;\n"
999          << "void main (void) {\n"
1000          << "    outColor = vec4(0.0, 0.0, 1.0, 1.0);\n"
1001          << "}\n";
1002     dst.glslSources.add("frag") << glu::FragmentSource(frag.str());
1003 }
1004 
createInstance(Context & context) const1005 TestInstance *NoStencilAttachmentCase::createInstance(Context &context) const
1006 {
1007     return new NoStencilAttachmentInstance(context, m_params);
1008 }
1009 
1010 // The goal here is indicating the stencil attachment is not present, either because there is no stencil aspect in the depth/stencil
1011 // format or because (when using dynamic rendering) the stencil attachment and format are null/unused respectively. Despite this
1012 // setup, in the depth/stencil pipeline state or dynamic state, we will indicate the stencil test is enabled.
1013 //
1014 // According to the spec, if there is no stencil attachment, the stencil test should not modify coverage and should be effectively
1015 // disabled.
iterate(void)1016 tcu::TestStatus NoStencilAttachmentInstance::iterate(void)
1017 {
1018     const auto &ctx        = m_context.getContextCommonData();
1019     const auto colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
1020     const auto tcuColorFmt = mapVkFormat(colorFormat);
1021     const auto tcuDSFmt    = mapVkFormat(m_params.format);
1022     const auto clearColor  = NoStencilAttachmentCase::getClearColor();
1023     const auto geomColor   = NoStencilAttachmentCase::getGeometryColor();
1024     const tcu::Vec4 threshold(0.0f, 0.0f, 0.0f, 0.0f); // When using 0 and 1 only, we expect exact results.
1025     const auto dataStages     = VK_SHADER_STAGE_VERTEX_BIT;
1026     const float clearDepth    = 0.5f;
1027     const float geomDepth     = 0.75f;
1028     const uint32_t stencilClr = 255u;
1029     const uint32_t stencilRef = 128u;
1030     const bool useDR          = m_params.useDynamicRendering();
1031 
1032     // Formats used to verify the different aspects.
1033     const bool hasDepth   = tcu::hasDepthComponent(tcuDSFmt.order);
1034     const bool hasStencil = tcu::hasStencilComponent(tcuDSFmt.order);
1035 
1036     DE_ASSERT(hasDepth);
1037 
1038     const auto depthCopyFormat   = (hasDepth ? getDepthCopyFormat(m_params.format) : tcu::TextureFormat());
1039     const auto stencilCopyFormat = (hasStencil ? getStencilCopyFormat(m_params.format) : tcu::TextureFormat());
1040 
1041     VkImageCreateInfo colorCreateInfo;
1042     VkImageCreateInfo dsCreateInfo;
1043 
1044     NoStencilAttachmentCase::getImageCreateInfo(&colorCreateInfo, colorFormat);
1045     NoStencilAttachmentCase::getImageCreateInfo(&dsCreateInfo, m_params.format);
1046 
1047     const auto &vkExtent  = colorCreateInfo.extent;
1048     const auto fbExtent   = tcu::IVec3(static_cast<int>(vkExtent.width), static_cast<int>(vkExtent.height),
1049                                        static_cast<int>(vkExtent.depth));
1050     const auto pixelCount = fbExtent.x() * fbExtent.y() * fbExtent.z();
1051     const auto colorSRR   = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, colorCreateInfo.mipLevels, 0u,
1052                                                       colorCreateInfo.arrayLayers);
1053     const auto dsSRR      = makeImageSubresourceRange(getImageAspectFlags(tcuDSFmt), 0u, dsCreateInfo.mipLevels, 0u,
1054                                                       dsCreateInfo.arrayLayers);
1055     const auto colorSRL   = makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, colorCreateInfo.arrayLayers);
1056     const auto depthSRL   = makeImageSubresourceLayers(VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 0u, dsCreateInfo.arrayLayers);
1057     const auto stencilSRL = makeImageSubresourceLayers(VK_IMAGE_ASPECT_STENCIL_BIT, 0u, 0u, dsCreateInfo.arrayLayers);
1058 
1059     // Color buffer with verification buffer.
1060     ImageWithBuffer colorBuffer(ctx.vkd, ctx.device, ctx.allocator, colorCreateInfo.extent, colorCreateInfo.format,
1061                                 colorCreateInfo.usage, colorCreateInfo.imageType, colorSRR, colorCreateInfo.arrayLayers,
1062                                 colorCreateInfo.samples, colorCreateInfo.tiling, colorCreateInfo.mipLevels,
1063                                 colorCreateInfo.sharingMode);
1064 
1065     ImageWithMemory dsBuffer(ctx.vkd, ctx.device, ctx.allocator, dsCreateInfo, MemoryRequirement::Any);
1066     const auto dsView =
1067         makeImageView(ctx.vkd, ctx.device, dsBuffer.get(), VK_IMAGE_VIEW_TYPE_2D, dsCreateInfo.format, dsSRR);
1068 
1069     // Verification buffers for depth/stencil.
1070     using BufferWithMemoryPtr = std::unique_ptr<BufferWithMemory>;
1071 
1072     BufferWithMemoryPtr depthVerifBuffer;
1073     BufferWithMemoryPtr stencilVerifBuffer;
1074 
1075     VkDeviceSize depthVerifBufferSize   = 0ull;
1076     VkDeviceSize stencilVerifBufferSize = 0ull;
1077 
1078     if (hasDepth)
1079     {
1080         depthVerifBufferSize  = static_cast<VkDeviceSize>(tcu::getPixelSize(depthCopyFormat) * pixelCount);
1081         const auto createInfo = makeBufferCreateInfo(depthVerifBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1082         depthVerifBuffer.reset(
1083             new BufferWithMemory(ctx.vkd, ctx.device, ctx.allocator, createInfo, MemoryRequirement::HostVisible));
1084     }
1085 
1086     if (hasStencil)
1087     {
1088         stencilVerifBufferSize = static_cast<VkDeviceSize>(tcu::getPixelSize(stencilCopyFormat) * pixelCount);
1089         const auto createInfo  = makeBufferCreateInfo(stencilVerifBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1090         stencilVerifBuffer.reset(
1091             new BufferWithMemory(ctx.vkd, ctx.device, ctx.allocator, createInfo, MemoryRequirement::HostVisible));
1092     }
1093 
1094     const std::vector<VkImageView> fbViews{colorBuffer.getImageView(), *dsView};
1095 
1096     // Push constants.
1097     const auto pcSize  = static_cast<uint32_t>(sizeof(geomDepth));
1098     const auto pcRange = makePushConstantRange(dataStages, 0u, pcSize);
1099 
1100     const PipelineLayoutWrapper pipelineLayout(m_params.pipelineConstructionType, ctx.vkd, ctx.device, VK_NULL_HANDLE,
1101                                                &pcRange);
1102 
1103     const auto renderPass  = (useDR ? Move<VkRenderPass>() :
1104                                       makeRenderPass(ctx.vkd, ctx.device, colorCreateInfo.format, dsCreateInfo.format));
1105     const auto framebuffer = (useDR ? Move<VkFramebuffer>() :
1106                                       makeFramebuffer(ctx.vkd, ctx.device, *renderPass, de::sizeU32(fbViews),
1107                                                       de::dataOrNull(fbViews), colorCreateInfo.extent.width,
1108                                                       colorCreateInfo.extent.height, colorCreateInfo.arrayLayers));
1109 
1110     // Modules.
1111     const auto &binaries = m_context.getBinaryCollection();
1112     const ShaderWrapper vertModule(ctx.vkd, ctx.device, binaries.get("vert"));
1113     const ShaderWrapper fragModule(ctx.vkd, ctx.device, binaries.get("frag"));
1114     const ShaderWrapper nullModule;
1115 
1116     const std::vector<VkViewport> viewports(1u, makeViewport(colorCreateInfo.extent));
1117     const std::vector<VkRect2D> scissors(1u, makeRect2D(colorCreateInfo.extent));
1118 
1119     // Depth/stencil state: note how, despite not having a stencil attachment, we enable the stencil test in a way that will not
1120     // preserve the stencil clear value no matter if the test passes or not.
1121     const auto stencilOpState = makeStencilOpState(VK_STENCIL_OP_ZERO, VK_STENCIL_OP_DECREMENT_AND_CLAMP,
1122                                                    VK_STENCIL_OP_INVERT, VK_COMPARE_OP_EQUAL, 0xFFu, 0xFFu, stencilRef);
1123 
1124     const VkPipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo = {
1125         VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
1126         nullptr,                                                    // const void* pNext;
1127         0u,                                                         // VkPipelineDepthStencilStateCreateFlags flags;
1128         VK_TRUE,                                                    // VkBool32 depthTestEnable;
1129         VK_TRUE,                                                    // VkBool32 depthWriteEnable;
1130         VK_COMPARE_OP_GREATER,                                      // VkCompareOp depthCompareOp;
1131         VK_FALSE,                                                   // VkBool32 depthBoundsTestEnable;
1132         (m_params.dynamicEnable ? VK_FALSE : VK_TRUE),              // VkBool32 stencilTestEnable;
1133         stencilOpState,                                             // VkStencilOpState front;
1134         stencilOpState,                                             // VkStencilOpState back;
1135         0.0f,                                                       // float minDepthBounds;
1136         1.0f,                                                       // float maxDepthBounds;
1137     };
1138 
1139     const VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo = initVulkanStructure();
1140 
1141 #ifndef CTS_USES_VULKANSC
1142     // When using dynamic rendering, we'll signal the lack of a stencil attachment using VK_FORMAT_UNDEFINED for the stencil format.
1143     VkPipelineRenderingCreateInfo pipelineRenderingCreateInfo = {
1144         VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO, // VkStructureType sType;
1145         nullptr,                                          // const void* pNext;
1146         0u,                                               // uint32_t viewMask;
1147         1u,                                               // uint32_t colorAttachmentCount;
1148         &colorCreateInfo.format,                          // const VkFormat* pColorAttachmentFormats;
1149         dsCreateInfo.format,                              // VkFormat depthAttachmentFormat;
1150         VK_FORMAT_UNDEFINED,                              // VkFormat stencilAttachmentFormat;
1151     };
1152 #endif // CTS_USES_VULKANSC
1153 
1154     PipelineRenderingCreateInfoWrapper pipelineRenderingCreateInfoPtr(
1155 #ifndef CTS_USES_VULKANSC
1156         &pipelineRenderingCreateInfo
1157 #else
1158         nullptr
1159 #endif // CTS_USES_VULKANSC
1160     );
1161 
1162     std::vector<VkDynamicState> dynamicStates;
1163     if (m_params.dynamicEnable)
1164         dynamicStates.push_back(VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE_EXT);
1165 
1166     const VkPipelineDynamicStateCreateInfo dynamicStateCreateInfo = {
1167         VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType;
1168         nullptr,                                              // const void* pNext;
1169         0u,                                                   // VkPipelineDynamicStateCreateFlags flags;
1170         de::sizeU32(dynamicStates),                           // uint32_t dynamicStateCount;
1171         de::dataOrNull(dynamicStates),                        // const VkDynamicState* pDynamicStates;
1172     };
1173 
1174     GraphicsPipelineWrapper pipelineWrapper(ctx.vki, ctx.vkd, ctx.physicalDevice, ctx.device,
1175                                             m_context.getDeviceExtensions(), m_params.pipelineConstructionType);
1176 
1177     pipelineWrapper.setDefaultTopology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
1178         .setDefaultRasterizationState()
1179         .setDefaultColorBlendState()
1180         .setDefaultMultisampleState()
1181         .setDynamicState(&dynamicStateCreateInfo)
1182         .setupVertexInputState(&vertexInputStateCreateInfo)
1183         .setupPreRasterizationShaderState(viewports, scissors, pipelineLayout, *renderPass, 0u, vertModule, nullptr,
1184                                           nullModule, nullModule, nullModule, nullptr, nullptr,
1185                                           pipelineRenderingCreateInfoPtr)
1186         .setupFragmentShaderState(pipelineLayout, *renderPass, 0u, fragModule, &depthStencilStateCreateInfo)
1187         .setupFragmentOutputState(*renderPass, 0u)
1188         .setMonolithicPipelineLayout(pipelineLayout)
1189         .buildPipeline();
1190 
1191     CommandPoolWithBuffer cmd(ctx.vkd, ctx.device, ctx.qfIndex);
1192     const auto cmdBuffer = *cmd.cmdBuffer;
1193 
1194     const std::vector<VkClearValue> clearValues{
1195         makeClearValueColor(clearColor),
1196         makeClearValueDepthStencil(clearDepth, stencilClr),
1197     };
1198 
1199     beginCommandBuffer(ctx.vkd, cmdBuffer);
1200 
1201     if (useDR)
1202     {
1203         // Transition image layouts and clear images, then begin rendering.
1204         const std::vector<VkImageMemoryBarrier> preClearBarriers{
1205             makeImageMemoryBarrier(0u, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
1206                                    VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, colorBuffer.getImage(), colorSRR),
1207 
1208             makeImageMemoryBarrier(0u, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
1209                                    VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, dsBuffer.get(), dsSRR),
1210         };
1211 
1212         cmdPipelineImageMemoryBarrier(ctx.vkd, cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
1213                                       VK_PIPELINE_STAGE_TRANSFER_BIT, de::dataOrNull(preClearBarriers),
1214                                       de::sizeU32(preClearBarriers));
1215 
1216         // We want to use these clears instead of beginRendering clears to make sure the stencil aspect of the image is cleared too when present.
1217         ctx.vkd.cmdClearColorImage(cmdBuffer, colorBuffer.getImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1218                                    &clearValues.at(0u).color, 1u, &colorSRR);
1219         ctx.vkd.cmdClearDepthStencilImage(cmdBuffer, dsBuffer.get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1220                                           &clearValues.at(1u).depthStencil, 1u, &dsSRR);
1221 
1222         const std::vector<VkImageMemoryBarrier> postClearBarriers{
1223             makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT,
1224                                    (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT),
1225                                    VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
1226                                    colorBuffer.getImage(), colorSRR),
1227 
1228             makeImageMemoryBarrier(
1229                 VK_ACCESS_TRANSFER_WRITE_BIT,
1230                 (VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT),
1231                 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, dsBuffer.get(),
1232                 dsSRR),
1233         };
1234 
1235         const auto srcStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
1236         const auto dstStage = (VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
1237                                VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT);
1238 
1239         cmdPipelineImageMemoryBarrier(ctx.vkd, cmdBuffer, srcStage, dstStage, de::dataOrNull(postClearBarriers),
1240                                       de::sizeU32(postClearBarriers));
1241 
1242 #ifndef CTS_USES_VULKANSC
1243         const VkRenderingAttachmentInfo colorAttInfo = {
1244             VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,     // VkStructureType sType;
1245             nullptr,                                         // const void* pNext;
1246             colorBuffer.getImageView(),                      // VkImageView imageView;
1247             VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,        // VkImageLayout imageLayout;
1248             VK_RESOLVE_MODE_NONE,                            // VkResolveModeFlagBits resolveMode;
1249             VK_NULL_HANDLE,                                  // VkImageView resolveImageView;
1250             VK_IMAGE_LAYOUT_UNDEFINED,                       // VkImageLayout resolveImageLayout;
1251             VK_ATTACHMENT_LOAD_OP_LOAD,                      // VkAttachmentLoadOp loadOp;
1252             VK_ATTACHMENT_STORE_OP_STORE,                    // VkAttachmentStoreOp storeOp;
1253             /*unused*/ makeClearValueColor(tcu::Vec4(0.0f)), // VkClearValue clearValue;
1254         };
1255 
1256         const VkRenderingAttachmentInfo depthAttInfo = {
1257             VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,      // VkStructureType sType;
1258             nullptr,                                          // const void* pNext;
1259             *dsView,                                          // VkImageView imageView;
1260             VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout imageLayout;
1261             VK_RESOLVE_MODE_NONE,                             // VkResolveModeFlagBits resolveMode;
1262             VK_NULL_HANDLE,                                   // VkImageView resolveImageView;
1263             VK_IMAGE_LAYOUT_UNDEFINED,                        // VkImageLayout resolveImageLayout;
1264             VK_ATTACHMENT_LOAD_OP_LOAD,                       // VkAttachmentLoadOp loadOp;
1265             VK_ATTACHMENT_STORE_OP_STORE,                     // VkAttachmentStoreOp storeOp;
1266             /*unused*/ makeClearValueColor(tcu::Vec4(0.0f)),  // VkClearValue clearValue;
1267         };
1268 
1269         const VkRenderingInfo renderingInfo = {
1270             VK_STRUCTURE_TYPE_RENDERING_INFO, // VkStructureType sType;
1271             nullptr,                          // const void* pNext;
1272             0u,                               // VkRenderingFlags flags;
1273             scissors.at(0u),                  // VkRect2D renderArea;
1274             colorCreateInfo.arrayLayers,      // uint32_t layerCount;
1275             0u,                               // uint32_t viewMask;
1276             1u,                               // uint32_t colorAttachmentCount;
1277             &colorAttInfo,                    // const VkRenderingAttachmentInfo* pColorAttachments;
1278             &depthAttInfo,                    // const VkRenderingAttachmentInfo* pDepthAttachment;
1279             nullptr,                          // const VkRenderingAttachmentInfo* pStencilAttachment;
1280         };
1281 
1282         ctx.vkd.cmdBeginRendering(cmdBuffer, &renderingInfo);
1283 #else
1284         DE_ASSERT(false);
1285 #endif // CTS_USES_VULKANSC
1286     }
1287     else
1288         beginRenderPass(ctx.vkd, cmdBuffer, *renderPass, *framebuffer, scissors.at(0u), de::sizeU32(clearValues),
1289                         de::dataOrNull(clearValues));
1290 
1291     pipelineWrapper.bind(cmdBuffer);
1292     ctx.vkd.cmdPushConstants(cmdBuffer, *pipelineLayout, dataStages, 0u, pcSize, &geomDepth);
1293     if (m_params.dynamicEnable)
1294     {
1295 #ifndef CTS_USES_VULKANSC
1296         ctx.vkd.cmdSetStencilTestEnable(cmdBuffer, VK_TRUE);
1297 #else
1298         ctx.vkd.cmdSetStencilTestEnableEXT(cmdBuffer, VK_TRUE);
1299 #endif // CTS_USES_VULKANSC
1300     }
1301     ctx.vkd.cmdDraw(cmdBuffer, 3u, 1u, 0u, 0u);
1302 
1303     if (useDR)
1304     {
1305 #ifndef CTS_USES_VULKANSC
1306         endRendering(ctx.vkd, cmdBuffer);
1307 #else
1308         DE_ASSERT(false);
1309 #endif // CTS_USES_VULKANSC
1310     }
1311     else
1312         endRenderPass(ctx.vkd, cmdBuffer);
1313 
1314     {
1315         const std::vector<VkImageMemoryBarrier> imgMemoryBarriers{
1316             makeImageMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
1317                                    VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1318                                    colorBuffer.getImage(), colorSRR),
1319 
1320             makeImageMemoryBarrier(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
1321                                    VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
1322                                    VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dsBuffer.get(), dsSRR),
1323         };
1324 
1325         const auto srcStages = (VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
1326                                 VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT);
1327         const auto dstStages = VK_PIPELINE_STAGE_TRANSFER_BIT;
1328 
1329         cmdPipelineImageMemoryBarrier(ctx.vkd, cmdBuffer, srcStages, dstStages, de::dataOrNull(imgMemoryBarriers),
1330                                       de::sizeU32(imgMemoryBarriers));
1331 
1332         const auto colorRegion = makeBufferImageCopy(vkExtent, colorSRL);
1333         ctx.vkd.cmdCopyImageToBuffer(cmdBuffer, colorBuffer.getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1334                                      colorBuffer.getBuffer(), 1u, &colorRegion);
1335 
1336         if (hasDepth)
1337         {
1338             const auto depthRegion = makeBufferImageCopy(vkExtent, depthSRL);
1339             ctx.vkd.cmdCopyImageToBuffer(cmdBuffer, dsBuffer.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1340                                          depthVerifBuffer->get(), 1u, &depthRegion);
1341         }
1342 
1343         if (hasStencil)
1344         {
1345             const auto stencilRegion = makeBufferImageCopy(vkExtent, stencilSRL);
1346             ctx.vkd.cmdCopyImageToBuffer(cmdBuffer, dsBuffer.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1347                                          stencilVerifBuffer->get(), 1u, &stencilRegion);
1348         }
1349 
1350         const auto preHostBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
1351         cmdPipelineMemoryBarrier(ctx.vkd, cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
1352                                  &preHostBarrier);
1353     }
1354 
1355     endCommandBuffer(ctx.vkd, cmdBuffer);
1356     submitCommandsAndWait(ctx.vkd, ctx.device, ctx.queue, cmdBuffer);
1357 
1358     // Verify color output.
1359     invalidateAlloc(ctx.vkd, ctx.device, colorBuffer.getBufferAllocation());
1360     tcu::PixelBufferAccess resultAccess(tcuColorFmt, fbExtent, colorBuffer.getBufferAllocation().getHostPtr());
1361 
1362     tcu::TextureLevel referenceLevel(tcuColorFmt, fbExtent.x(), fbExtent.y());
1363     auto referenceAccess = referenceLevel.getAccess();
1364     tcu::clear(referenceAccess, geomColor);
1365 
1366     auto &log = m_context.getTestContext().getLog();
1367     if (!tcu::floatThresholdCompare(log, "ResultColor", "", referenceAccess, resultAccess, threshold,
1368                                     tcu::COMPARE_LOG_ON_ERROR))
1369         return tcu::TestStatus::fail("Unexpected color in result buffer; check log for details");
1370 
1371     // Verify depth/stencil if available.
1372     if (hasDepth)
1373     {
1374         const auto &allocation = depthVerifBuffer->getAllocation();
1375         invalidateAlloc(ctx.vkd, ctx.device, allocation);
1376 
1377         tcu::PixelBufferAccess resultDepth(depthCopyFormat, fbExtent, allocation.getHostPtr());
1378         tcu::TextureLevel referenceDepth(depthCopyFormat, fbExtent.x(), fbExtent.y());
1379         auto refDepthAccess = referenceDepth.getAccess();
1380 
1381         tcu::clearDepth(refDepthAccess, geomDepth);
1382         const float depthThreshold =
1383             0.000025f; // Should be good enough for D16, D24 and D32 given the depth values we're using.
1384 
1385         if (!tcu::dsThresholdCompare(log, "ResultDepth", "", refDepthAccess, resultDepth, depthThreshold,
1386                                      tcu::COMPARE_LOG_ON_ERROR))
1387             return tcu::TestStatus::fail("Unexpected depth in result buffer; check log for details");
1388     }
1389     if (hasStencil)
1390     {
1391         const auto &allocation = stencilVerifBuffer->getAllocation();
1392         invalidateAlloc(ctx.vkd, ctx.device, allocation);
1393 
1394         tcu::PixelBufferAccess resultStencil(stencilCopyFormat, fbExtent, allocation.getHostPtr());
1395         tcu::TextureLevel referenceStencil(stencilCopyFormat, fbExtent.x(), fbExtent.y());
1396         auto refStencilAccess = referenceStencil.getAccess();
1397 
1398         tcu::clearStencil(refStencilAccess, stencilClr);
1399         const float stencilThreshold = 0.0f; // This is actually not used for stencil.
1400 
1401         if (!tcu::dsThresholdCompare(log, "ResultStencil", "", refStencilAccess, resultStencil, stencilThreshold,
1402                                      tcu::COMPARE_LOG_ON_ERROR))
1403             return tcu::TestStatus::fail("Unexpected stencil value in result buffer; check log for details");
1404     }
1405 
1406     return tcu::TestStatus::pass("Pass");
1407 }
1408 
1409 // Utilities for test names
1410 
getShortName(VkStencilOp stencilOp)1411 const char *getShortName(VkStencilOp stencilOp)
1412 {
1413     switch (stencilOp)
1414     {
1415     case VK_STENCIL_OP_KEEP:
1416         return "keep";
1417     case VK_STENCIL_OP_ZERO:
1418         return "zero";
1419     case VK_STENCIL_OP_REPLACE:
1420         return "repl";
1421     case VK_STENCIL_OP_INCREMENT_AND_CLAMP:
1422         return "incc";
1423     case VK_STENCIL_OP_DECREMENT_AND_CLAMP:
1424         return "decc";
1425     case VK_STENCIL_OP_INVERT:
1426         return "inv";
1427     case VK_STENCIL_OP_INCREMENT_AND_WRAP:
1428         return "wrap";
1429     case VK_STENCIL_OP_DECREMENT_AND_WRAP:
1430         return "decw";
1431 
1432     default:
1433         DE_FATAL("Invalid VkStencilOpState value");
1434     }
1435     return nullptr;
1436 }
1437 
getFormatCaseName(VkFormat format)1438 std::string getFormatCaseName(VkFormat format)
1439 {
1440     const std::string fullName = getFormatName(format);
1441 
1442     DE_ASSERT(de::beginsWith(fullName, "VK_FORMAT_"));
1443 
1444     return de::toLower(fullName.substr(10));
1445 }
1446 
1447 } // namespace
1448 
createStencilTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType)1449 tcu::TestCaseGroup *createStencilTests(tcu::TestContext &testCtx, PipelineConstructionType pipelineConstructionType)
1450 {
1451     const VkFormat stencilFormats[] = {VK_FORMAT_S8_UINT, VK_FORMAT_D16_UNORM_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT,
1452                                        VK_FORMAT_D32_SFLOAT_S8_UINT};
1453 
1454     DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(compareOps) == 8);
1455     DE_STATIC_ASSERT(vk::VK_COMPARE_OP_LAST == 8);
1456 
1457     static const char *compareOpNames[8] = {"comp_never",
1458                                             "comp_less",
1459                                             "comp_equal",
1460                                             "comp_less_or_equal",
1461                                             "comp_greater",
1462                                             "comp_not_equal",
1463                                             "comp_greater_or_equal",
1464                                             "comp_always"};
1465 
1466     // Stencil tests
1467     de::MovePtr<tcu::TestCaseGroup> stencilTests(new tcu::TestCaseGroup(testCtx, "stencil"));
1468     // Stencil tests with no color attachment
1469     de::MovePtr<tcu::TestCaseGroup> noColorAttachmentTests(new tcu::TestCaseGroup(testCtx, "nocolor"));
1470     const bool colorAttachmentEnabled[] = {true, false};
1471 
1472     for (uint32_t colorAttachmentEnabledIdx = 0; colorAttachmentEnabledIdx < DE_LENGTH_OF_ARRAY(colorAttachmentEnabled);
1473          colorAttachmentEnabledIdx++)
1474     {
1475         const bool colorEnabled = colorAttachmentEnabled[colorAttachmentEnabledIdx];
1476         de::MovePtr<tcu::TestCaseGroup> formatTests(new tcu::TestCaseGroup(testCtx, "format"));
1477         StencilOpStateUniqueRandomIterator stencilOpItr(123);
1478 
1479         for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(stencilFormats); formatNdx++)
1480         {
1481             const VkFormat stencilFormat       = stencilFormats[formatNdx];
1482             const bool hasDepth                = tcu::hasDepthComponent(mapVkFormat(stencilFormat).order);
1483             const bool hasStencil              = tcu::hasStencilComponent(mapVkFormat(stencilFormat).order);
1484             const int separateLayoutsLoopCount = (hasDepth && hasStencil) ? 2 : 1;
1485 
1486             for (int separateDepthStencilLayouts = 0; separateDepthStencilLayouts < separateLayoutsLoopCount;
1487                  ++separateDepthStencilLayouts)
1488             {
1489                 const bool useSeparateDepthStencilLayouts = bool(separateDepthStencilLayouts);
1490 
1491                 de::MovePtr<tcu::TestCaseGroup> formatTest(new tcu::TestCaseGroup(
1492                     testCtx,
1493                     (getFormatCaseName(stencilFormat) + ((useSeparateDepthStencilLayouts) ? "_separate_layouts" : ""))
1494                         .c_str()));
1495 
1496                 de::MovePtr<tcu::TestCaseGroup> stencilStateTests;
1497                 {
1498                     std::ostringstream desc;
1499                     desc << "Draws 4 quads with the following depths and dynamic stencil states: ";
1500 
1501                     for (int quadNdx = 0; quadNdx < StencilTest::QUAD_COUNT; quadNdx++)
1502                     {
1503                         const StencilTest::StencilStateConfig &stencilConfig =
1504                             StencilTest::s_stencilStateConfigs[quadNdx];
1505 
1506                         desc << "(" << quadNdx << ") "
1507                              << "z = " << StencilTest::s_quadDepths[quadNdx] << ", "
1508                              << "frontReadMask = " << stencilConfig.frontReadMask << ", "
1509                              << "frontWriteMask = " << stencilConfig.frontWriteMask << ", "
1510                              << "frontRef = " << stencilConfig.frontRef << ", "
1511                              << "backReadMask = " << stencilConfig.backReadMask << ", "
1512                              << "backWriteMask = " << stencilConfig.backWriteMask << ", "
1513                              << "backRef = " << stencilConfig.backRef;
1514                     }
1515 
1516                     stencilStateTests = de::MovePtr<tcu::TestCaseGroup>(new tcu::TestCaseGroup(testCtx, "states"));
1517                 }
1518 
1519                 stencilOpItr.reset();
1520 
1521                 for (uint32_t failOpNdx = 0u; failOpNdx < DE_LENGTH_OF_ARRAY(stencilOps); failOpNdx++)
1522                 {
1523                     const std::string failOpName = std::string("fail_") + getShortName(stencilOps[failOpNdx]);
1524                     de::MovePtr<tcu::TestCaseGroup> failOpTest(new tcu::TestCaseGroup(testCtx, failOpName.c_str()));
1525 
1526                     for (uint32_t passOpNdx = 0u; passOpNdx < DE_LENGTH_OF_ARRAY(stencilOps); passOpNdx++)
1527                     {
1528                         const std::string passOpName = std::string("pass_") + getShortName(stencilOps[passOpNdx]);
1529                         de::MovePtr<tcu::TestCaseGroup> passOpTest(new tcu::TestCaseGroup(testCtx, passOpName.c_str()));
1530 
1531                         for (uint32_t dFailOpNdx = 0u; dFailOpNdx < DE_LENGTH_OF_ARRAY(stencilOps); dFailOpNdx++)
1532                         {
1533                             const std::string dFailOpName =
1534                                 std::string("dfail_") + getShortName(stencilOps[dFailOpNdx]);
1535                             de::MovePtr<tcu::TestCaseGroup> dFailOpTest(
1536                                 new tcu::TestCaseGroup(testCtx, dFailOpName.c_str()));
1537 
1538                             for (uint32_t compareOpNdx = 0u; compareOpNdx < DE_LENGTH_OF_ARRAY(compareOps);
1539                                  compareOpNdx++)
1540                             {
1541                                 // Iterate front set of stencil state in ascending order
1542                                 const VkStencilOpState stencilStateFront = {
1543                                     stencilOps[failOpNdx],    // failOp
1544                                     stencilOps[passOpNdx],    // passOp
1545                                     stencilOps[dFailOpNdx],   // depthFailOp
1546                                     compareOps[compareOpNdx], // compareOp
1547                                     0x0,                      // compareMask
1548                                     0x0,                      // writeMask
1549                                     0x0                       // reference
1550                                 };
1551 
1552                                 // Iterate back set of stencil state in random order
1553                                 const VkStencilOpState stencilStateBack = stencilOpItr.next();
1554                                 const std::string caseName              = compareOpNames[compareOpNdx];
1555 
1556                                 dFailOpTest->addChild(new StencilTest(
1557                                     testCtx, caseName, pipelineConstructionType, stencilFormat, stencilStateFront,
1558                                     stencilStateBack, colorEnabled, useSeparateDepthStencilLayouts));
1559                             }
1560                             passOpTest->addChild(dFailOpTest.release());
1561                         }
1562                         failOpTest->addChild(passOpTest.release());
1563                     }
1564                     stencilStateTests->addChild(failOpTest.release());
1565                 }
1566 
1567                 formatTest->addChild(stencilStateTests.release());
1568                 formatTests->addChild(formatTest.release());
1569             }
1570         }
1571 
1572         if (colorEnabled)
1573             stencilTests->addChild(formatTests.release());
1574         else
1575             noColorAttachmentTests->addChild(formatTests.release());
1576     }
1577 
1578     stencilTests->addChild(noColorAttachmentTests.release());
1579 
1580     // Tests attempting to enable the stencil test while not using a stencil attachment.
1581     const auto isNoStencilRelevantVariant =
1582         (pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC ||
1583          pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_SHADER_OBJECT_UNLINKED_SPIRV ||
1584          pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_FAST_LINKED_LIBRARY);
1585     if (isNoStencilRelevantVariant)
1586     {
1587         de::MovePtr<tcu::TestCaseGroup> noStencilAttGroup(new tcu::TestCaseGroup(testCtx, "no_stencil_att"));
1588 
1589         const VkFormat depthComponentFormats[] = {
1590             VK_FORMAT_D16_UNORM,         VK_FORMAT_X8_D24_UNORM_PACK32, VK_FORMAT_D32_SFLOAT,
1591             VK_FORMAT_D16_UNORM_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT,   VK_FORMAT_D32_SFLOAT_S8_UINT,
1592         };
1593 
1594         for (const auto dynamicRendering : {false, true})
1595         {
1596             if (!dynamicRendering && isConstructionTypeShaderObject(pipelineConstructionType))
1597                 continue;
1598 
1599 #ifdef CTS_USES_VULKANSC
1600             if (dynamicRendering)
1601                 continue;
1602 #endif
1603 
1604             const char *renderingGroupName = (dynamicRendering ? "dynamic_rendering" : "render_passes");
1605             de::MovePtr<tcu::TestCaseGroup> renderingGroup(new tcu::TestCaseGroup(testCtx, renderingGroupName));
1606 
1607             for (const auto dynamicEnable : {false, true})
1608             {
1609                 const char *enableGroupName = (dynamicEnable ? "dynamic_enable" : "static_enable");
1610                 de::MovePtr<tcu::TestCaseGroup> dynEnableGroup(new tcu::TestCaseGroup(testCtx, enableGroupName));
1611 
1612                 for (const auto &depthComponentFormat : depthComponentFormats)
1613                 {
1614                     // When using classic render passes, we cannot indicate a separate stencil format and image.
1615                     const auto tcuFormat = mapVkFormat(depthComponentFormat);
1616                     if (!dynamicRendering && tcu::hasStencilComponent(tcuFormat.order))
1617                         continue;
1618 
1619                     const NoStencilAttachmentParams params{
1620                         pipelineConstructionType,
1621                         depthComponentFormat,
1622                         dynamicRendering,
1623                         dynamicEnable,
1624                     };
1625                     const std::string testName = getFormatCaseName(depthComponentFormat);
1626                     dynEnableGroup->addChild(new NoStencilAttachmentCase(testCtx, testName, params));
1627                 }
1628 
1629                 renderingGroup->addChild(dynEnableGroup.release());
1630             }
1631 
1632             noStencilAttGroup->addChild(renderingGroup.release());
1633         }
1634 
1635         stencilTests->addChild(noStencilAttGroup.release());
1636     }
1637 
1638     return stencilTests.release();
1639 }
1640 
1641 } // namespace pipeline
1642 } // namespace vkt
1643