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