Merge "Report Android extension pack tests as not supported" am: 03c395c60f
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / fragment_ops / vktFragmentOperationsEarlyFragmentTests.cpp
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
6  * Copyright (c) 2015 The Khronos Group Inc.
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 Early fragment tests
23  *//*--------------------------------------------------------------------*/
24
25 #include "vktFragmentOperationsEarlyFragmentTests.hpp"
26 #include "vktFragmentOperationsMakeUtil.hpp"
27 #include "vktTestCaseUtil.hpp"
28
29 #include "vkDefs.hpp"
30 #include "vkRef.hpp"
31 #include "vkRefUtil.hpp"
32 #include "vkPlatform.hpp"
33 #include "vkPrograms.hpp"
34 #include "vkMemUtil.hpp"
35 #include "vkBuilderUtil.hpp"
36 #include "vkStrUtil.hpp"
37 #include "vkTypeUtil.hpp"
38 #include "vkQueryUtil.hpp"
39 #include "vkImageUtil.hpp"
40
41 #include "tcuTestLog.hpp"
42
43 #include "deUniquePtr.hpp"
44 #include "deStringUtil.hpp"
45
46 #include <string>
47
48 namespace vkt
49 {
50 namespace FragmentOperations
51 {
52 namespace
53 {
54 using namespace vk;
55 using de::UniquePtr;
56
57 //! Basic 2D image.
58 inline VkImageCreateInfo makeImageCreateInfo (const tcu::IVec2& size, const VkFormat format, const VkImageUsageFlags usage)
59 {
60         const VkImageCreateInfo imageParams =
61         {
62                 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                                    // VkStructureType                      sType;
63                 DE_NULL,                                                                                                // const void*                          pNext;
64                 (VkImageCreateFlags)0,                                                                  // VkImageCreateFlags           flags;
65                 VK_IMAGE_TYPE_2D,                                                                               // VkImageType                          imageType;
66                 format,                                                                                                 // VkFormat                                     format;
67                 makeExtent3D(size.x(), size.y(), 1),                                    // VkExtent3D                           extent;
68                 1u,                                                                                                             // deUint32                                     mipLevels;
69                 1u,                                                                                                             // deUint32                                     arrayLayers;
70                 VK_SAMPLE_COUNT_1_BIT,                                                                  // VkSampleCountFlagBits        samples;
71                 VK_IMAGE_TILING_OPTIMAL,                                                                // VkImageTiling                        tiling;
72                 usage,                                                                                                  // VkImageUsageFlags            usage;
73                 VK_SHARING_MODE_EXCLUSIVE,                                                              // VkSharingMode                        sharingMode;
74                 0u,                                                                                                             // deUint32                                     queueFamilyIndexCount;
75                 DE_NULL,                                                                                                // const deUint32*                      pQueueFamilyIndices;
76                 VK_IMAGE_LAYOUT_UNDEFINED,                                                              // VkImageLayout                        initialLayout;
77         };
78         return imageParams;
79 }
80
81 void beginRenderPass (const DeviceInterface&    vk,
82                                           const VkCommandBuffer         commandBuffer,
83                                           const VkRenderPass            renderPass,
84                                           const VkFramebuffer           framebuffer,
85                                           const VkRect2D&                       renderArea,
86                                           const tcu::Vec4&                      clearColor,
87                                           const float                           clearDepth,
88                                           const deUint32                        clearStencil)
89 {
90         const VkClearValue clearValues[] =
91         {
92                 makeClearValueColor(clearColor),                                                // attachment 0
93                 makeClearValueDepthStencil(clearDepth, clearStencil),   // attachment 1
94         };
95
96         const VkRenderPassBeginInfo renderPassBeginInfo = {
97                 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,               // VkStructureType         sType;
98                 DE_NULL,                                                                                // const void*             pNext;
99                 renderPass,                                                                             // VkRenderPass            renderPass;
100                 framebuffer,                                                                    // VkFramebuffer           framebuffer;
101                 renderArea,                                                                             // VkRect2D                renderArea;
102                 DE_LENGTH_OF_ARRAY(clearValues),                                // uint32_t                clearValueCount;
103                 clearValues,                                                                    // const VkClearValue*     pClearValues;
104         };
105
106         vk.cmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
107 }
108
109 Move<VkRenderPass> makeRenderPass (const DeviceInterface&       vk,
110                                                                    const VkDevice                       device,
111                                                                    const VkFormat                       colorFormat,
112                                                                    const bool                           useDepthStencilAttachment,
113                                                                    const VkFormat                       depthStencilFormat)
114 {
115         const VkAttachmentDescription attachments[] =
116         {
117                 // color
118                 {
119                         (VkAttachmentDescriptionFlags)0,                                        // VkAttachmentDescriptionFlags         flags;
120                         colorFormat,                                                                            // VkFormat                                                     format;
121                         VK_SAMPLE_COUNT_1_BIT,                                                          // VkSampleCountFlagBits                        samples;
122                         VK_ATTACHMENT_LOAD_OP_CLEAR,                                            // VkAttachmentLoadOp                           loadOp;
123                         VK_ATTACHMENT_STORE_OP_STORE,                                           // VkAttachmentStoreOp                          storeOp;
124                         VK_ATTACHMENT_LOAD_OP_DONT_CARE,                                        // VkAttachmentLoadOp                           stencilLoadOp;
125                         VK_ATTACHMENT_STORE_OP_DONT_CARE,                                       // VkAttachmentStoreOp                          stencilStoreOp;
126                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                       // VkImageLayout                                        initialLayout;
127                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                       // VkImageLayout                                        finalLayout;
128                 },
129                 // depth/stencil
130                 {
131                         (VkAttachmentDescriptionFlags)0,                                        // VkAttachmentDescriptionFlags         flags;
132                         depthStencilFormat,                                                                     // VkFormat                                                     format;
133                         VK_SAMPLE_COUNT_1_BIT,                                                          // VkSampleCountFlagBits                        samples;
134                         VK_ATTACHMENT_LOAD_OP_CLEAR,                                            // VkAttachmentLoadOp                           loadOp;
135                         VK_ATTACHMENT_STORE_OP_STORE,                                           // VkAttachmentStoreOp                          storeOp;
136                         VK_ATTACHMENT_LOAD_OP_CLEAR,                                            // VkAttachmentLoadOp                           stencilLoadOp;
137                         VK_ATTACHMENT_STORE_OP_STORE,                                           // VkAttachmentStoreOp                          stencilStoreOp;
138                         VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,       // VkImageLayout                                        initialLayout;
139                         VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,       // VkImageLayout                                        finalLayout;
140                 }
141         };
142
143         const VkAttachmentReference unusedAttachmentReference =
144         {
145                 VK_ATTACHMENT_UNUSED,                                                           // deUint32                     attachment;
146                 VK_IMAGE_LAYOUT_UNDEFINED                                                       // VkImageLayout        layout;
147         };
148
149         const VkAttachmentReference colorAttachmentReference =
150         {
151                 0u,                                                                                                     // deUint32                     attachment;
152                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL                        // VkImageLayout        layout;
153         };
154
155         const VkAttachmentReference depthStencilAttachmentReference =
156         {
157                 1u,                                                                                                     // deUint32                     attachment;
158                 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL        // VkImageLayout        layout;
159         };
160
161         const VkAttachmentReference* pDepthStencilAttachment = (useDepthStencilAttachment ? &depthStencilAttachmentReference : &unusedAttachmentReference);
162
163         const VkSubpassDescription subpassDescription =
164         {
165                 0u,                                                                                                     // VkSubpassDescriptionFlags            flags;
166                 VK_PIPELINE_BIND_POINT_GRAPHICS,                                        // VkPipelineBindPoint                          pipelineBindPoint;
167                 0u,                                                                                                     // deUint32                                                     inputAttachmentCount;
168                 DE_NULL,                                                                                        // const VkAttachmentReference*         pInputAttachments;
169                 1u,                                                                                                     // deUint32                                                     colorAttachmentCount;
170                 &colorAttachmentReference,                                                      // const VkAttachmentReference*         pColorAttachments;
171                 DE_NULL,                                                                                        // const VkAttachmentReference*         pResolveAttachments;
172                 pDepthStencilAttachment,                                                        // const VkAttachmentReference*         pDepthStencilAttachment;
173                 0u,                                                                                                     // deUint32                                                     preserveAttachmentCount;
174                 DE_NULL                                                                                         // const deUint32*                                      pPreserveAttachments;
175         };
176
177         const VkRenderPassCreateInfo renderPassInfo =
178         {
179                 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,                      // VkStructureType                                      sType;
180                 DE_NULL,                                                                                        // const void*                                          pNext;
181                 (VkRenderPassCreateFlags)0,                                                     // VkRenderPassCreateFlags                      flags;
182                 (useDepthStencilAttachment ? 2u : 1u),                          // deUint32                                                     attachmentCount;
183                 attachments,                                                                            // const VkAttachmentDescription*       pAttachments;
184                 1u,                                                                                                     // deUint32                                                     subpassCount;
185                 &subpassDescription,                                                            // const VkSubpassDescription*          pSubpasses;
186                 0u,                                                                                                     // deUint32                                                     dependencyCount;
187                 DE_NULL                                                                                         // const VkSubpassDependency*           pDependencies;
188         };
189
190         return createRenderPass(vk, device, &renderPassInfo);
191 }
192
193 Move<VkFramebuffer> makeFramebuffer (const DeviceInterface&             vk,
194                                                                          const VkDevice                         device,
195                                                                          const VkRenderPass                     renderPass,
196                                                                          const deUint32                         attachmentCount,
197                                                                          const VkImageView*                     pAttachments,
198                                                                          const tcu::IVec2                       size)
199 {
200         const VkFramebufferCreateInfo framebufferInfo = {
201                 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,              // VkStructureType                             sType;
202                 DE_NULL,                                                                                // const void*                                 pNext;
203                 (VkFramebufferCreateFlags)0,                                    // VkFramebufferCreateFlags                    flags;
204                 renderPass,                                                                             // VkRenderPass                                renderPass;
205                 attachmentCount,                                                                // uint32_t                                    attachmentCount;
206                 pAttachments,                                                                   // const VkImageView*                          pAttachments;
207                 static_cast<deUint32>(size.x()),                                // uint32_t                                    width;
208                 static_cast<deUint32>(size.y()),                                // uint32_t                                    height;
209                 1u,                                                                                             // uint32_t                                    layers;
210         };
211
212         return createFramebuffer(vk, device, &framebufferInfo);
213 }
214
215 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface&   vk,
216                                                                            const VkDevice                       device,
217                                                                            const VkPipelineLayout       pipelineLayout,
218                                                                            const VkRenderPass           renderPass,
219                                                                            const VkShaderModule         vertexModule,
220                                                                            const VkShaderModule         fragmentModule,
221                                                                            const tcu::IVec2&            renderSize,
222                                                                            const bool                           enableDepthTest,
223                                                                            const bool                           enableStencilTest)
224 {
225         const VkVertexInputBindingDescription vertexInputBindingDescription =
226         {
227                 0u,                                                             // uint32_t                             binding;
228                 sizeof(tcu::Vec4),                              // uint32_t                             stride;         // Vertex is a 4-element vector XYZW, position only
229                 VK_VERTEX_INPUT_RATE_VERTEX,    // VkVertexInputRate    inputRate;
230         };
231
232         const VkVertexInputAttributeDescription vertexInputAttributeDescription =
233         {
234                 0u,                                                                     // uint32_t                     location;
235                 0u,                                                                     // uint32_t                     binding;
236                 VK_FORMAT_R32G32B32A32_SFLOAT,          // VkFormat                     format;
237                 0u,                                                                     // uint32_t                     offset;
238         };
239
240         const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
241         {
242                 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,      // VkStructureType                             sType;
243                 DE_NULL,                                                                                                        // const void*                                 pNext;
244                 (VkPipelineVertexInputStateCreateFlags)0,                                       // VkPipelineVertexInputStateCreateFlags       flags;
245                 1u,                                                                                                                     // uint32_t                                    vertexBindingDescriptionCount;
246                 &vertexInputBindingDescription,                                                         // const VkVertexInputBindingDescription*      pVertexBindingDescriptions;
247                 1u,                                                                                                                     // uint32_t                                    vertexAttributeDescriptionCount;
248                 &vertexInputAttributeDescription,                                                       // const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions;
249         };
250
251         const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo =
252         {
253                 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,    // VkStructureType                             sType;
254                 DE_NULL,                                                                                                                // const void*                                 pNext;
255                 (VkPipelineInputAssemblyStateCreateFlags)0,                                             // VkPipelineInputAssemblyStateCreateFlags     flags;
256                 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,                                                    // VkPrimitiveTopology                         topology;
257                 VK_FALSE,                                                                                                               // VkBool32                                    primitiveRestartEnable;
258         };
259
260         const VkViewport viewport = makeViewport(
261                 0.0f, 0.0f,
262                 static_cast<float>(renderSize.x()), static_cast<float>(renderSize.y()),
263                 0.0f, 1.0f);
264
265         const VkRect2D scissor = {
266                 makeOffset2D(0, 0),
267                 makeExtent2D(renderSize.x(), renderSize.y()),
268         };
269
270         const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo =
271         {
272                 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,  // VkStructureType                             sType;
273                 DE_NULL,                                                                                                // const void*                                 pNext;
274                 (VkPipelineViewportStateCreateFlags)0,                                  // VkPipelineViewportStateCreateFlags          flags;
275                 1u,                                                                                                             // uint32_t                                    viewportCount;
276                 &viewport,                                                                                              // const VkViewport*                           pViewports;
277                 1u,                                                                                                             // uint32_t                                    scissorCount;
278                 &scissor,                                                                                               // const VkRect2D*                             pScissors;
279         };
280
281         const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo =
282         {
283                 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,             // VkStructureType                          sType;
284                 DE_NULL,                                                                                                                // const void*                              pNext;
285                 (VkPipelineRasterizationStateCreateFlags)0,                                             // VkPipelineRasterizationStateCreateFlags  flags;
286                 VK_FALSE,                                                                                                               // VkBool32                                 depthClampEnable;
287                 VK_FALSE,                                                                                                               // VkBool32                                 rasterizerDiscardEnable;
288                 VK_POLYGON_MODE_FILL,                                                                                   // VkPolygonMode                                                        polygonMode;
289                 VK_CULL_MODE_NONE,                                                                                              // VkCullModeFlags                                                      cullMode;
290                 VK_FRONT_FACE_COUNTER_CLOCKWISE,                                                                // VkFrontFace                                                          frontFace;
291                 VK_FALSE,                                                                                                               // VkBool32                                                                     depthBiasEnable;
292                 0.0f,                                                                                                                   // float                                                                        depthBiasConstantFactor;
293                 0.0f,                                                                                                                   // float                                                                        depthBiasClamp;
294                 0.0f,                                                                                                                   // float                                                                        depthBiasSlopeFactor;
295                 1.0f,                                                                                                                   // float                                                                        lineWidth;
296         };
297
298         const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo =
299         {
300                 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,       // VkStructureType                                                      sType;
301                 DE_NULL,                                                                                                        // const void*                                                          pNext;
302                 (VkPipelineMultisampleStateCreateFlags)0,                                       // VkPipelineMultisampleStateCreateFlags        flags;
303                 VK_SAMPLE_COUNT_1_BIT,                                                                          // VkSampleCountFlagBits                                        rasterizationSamples;
304                 VK_FALSE,                                                                                                       // VkBool32                                                                     sampleShadingEnable;
305                 0.0f,                                                                                                           // float                                                                        minSampleShading;
306                 DE_NULL,                                                                                                        // const VkSampleMask*                                          pSampleMask;
307                 VK_FALSE,                                                                                                       // VkBool32                                                                     alphaToCoverageEnable;
308                 VK_FALSE                                                                                                        // VkBool32                                                                     alphaToOneEnable;
309         };
310
311         const VkStencilOpState stencilOpState = makeStencilOpState(
312                 VK_STENCIL_OP_KEEP,             // stencil fail
313                 VK_STENCIL_OP_KEEP,             // depth & stencil pass
314                 VK_STENCIL_OP_KEEP,             // depth only fail
315                 VK_COMPARE_OP_EQUAL,    // compare op
316                 1u,                                             // compare mask
317                 1u,                                             // write mask
318                 1u);                                    // reference
319
320         VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo =
321         {
322                 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,     // VkStructureType                                                      sType;
323                 DE_NULL,                                                                                                        // const void*                                                          pNext;
324                 (VkPipelineDepthStencilStateCreateFlags)0,                                      // VkPipelineDepthStencilStateCreateFlags       flags;
325                 enableDepthTest,                                                                                        // VkBool32                                                                     depthTestEnable;
326                 VK_TRUE,                                                                                                        // VkBool32                                                                     depthWriteEnable;
327                 VK_COMPARE_OP_LESS,                                                                                     // VkCompareOp                                                          depthCompareOp;
328                 VK_FALSE,                                                                                                       // VkBool32                                                                     depthBoundsTestEnable;
329                 enableStencilTest,                                                                                      // VkBool32                                                                     stencilTestEnable;
330                 stencilOpState,                                                                                         // VkStencilOpState                                                     front;
331                 stencilOpState,                                                                                         // VkStencilOpState                                                     back;
332                 0.0f,                                                                                                           // float                                                                        minDepthBounds;
333                 1.0f,                                                                                                           // float                                                                        maxDepthBounds;
334         };
335
336         const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
337         // Number of blend attachments must equal the number of color attachments.
338         const VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState =
339         {
340                 VK_FALSE,                                                       // VkBool32                                     blendEnable;
341                 VK_BLEND_FACTOR_ONE,                            // VkBlendFactor                        srcColorBlendFactor;
342                 VK_BLEND_FACTOR_ZERO,                           // VkBlendFactor                        dstColorBlendFactor;
343                 VK_BLEND_OP_ADD,                                        // VkBlendOp                            colorBlendOp;
344                 VK_BLEND_FACTOR_ONE,                            // VkBlendFactor                        srcAlphaBlendFactor;
345                 VK_BLEND_FACTOR_ZERO,                           // VkBlendFactor                        dstAlphaBlendFactor;
346                 VK_BLEND_OP_ADD,                                        // VkBlendOp                            alphaBlendOp;
347                 colorComponentsAll,                                     // VkColorComponentFlags        colorWriteMask;
348         };
349
350         const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo =
351         {
352                 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,       // VkStructureType                                                              sType;
353                 DE_NULL,                                                                                                        // const void*                                                                  pNext;
354                 (VkPipelineColorBlendStateCreateFlags)0,                                        // VkPipelineColorBlendStateCreateFlags                 flags;
355                 VK_FALSE,                                                                                                       // VkBool32                                                                             logicOpEnable;
356                 VK_LOGIC_OP_COPY,                                                                                       // VkLogicOp                                                                    logicOp;
357                 1u,                                                                                                                     // deUint32                                                                             attachmentCount;
358                 &pipelineColorBlendAttachmentState,                                                     // const VkPipelineColorBlendAttachmentState*   pAttachments;
359                 { 0.0f, 0.0f, 0.0f, 0.0f },                                                                     // float                                                                                blendConstants[4];
360         };
361
362         const VkPipelineShaderStageCreateInfo pShaderStages[] =
363         {
364                 {
365                         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,    // VkStructureType                                              sType;
366                         DE_NULL,                                                                                                // const void*                                                  pNext;
367                         (VkPipelineShaderStageCreateFlags)0,                                    // VkPipelineShaderStageCreateFlags             flags;
368                         VK_SHADER_STAGE_VERTEX_BIT,                                                             // VkShaderStageFlagBits                                stage;
369                         vertexModule,                                                                                   // VkShaderModule                                               module;
370                         "main",                                                                                                 // const char*                                                  pName;
371                         DE_NULL,                                                                                                // const VkSpecializationInfo*                  pSpecializationInfo;
372                 },
373                 {
374                         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,    // VkStructureType                                              sType;
375                         DE_NULL,                                                                                                // const void*                                                  pNext;
376                         (VkPipelineShaderStageCreateFlags)0,                                    // VkPipelineShaderStageCreateFlags             flags;
377                         VK_SHADER_STAGE_FRAGMENT_BIT,                                                   // VkShaderStageFlagBits                                stage;
378                         fragmentModule,                                                                                 // VkShaderModule                                               module;
379                         "main",                                                                                                 // const char*                                                  pName;
380                         DE_NULL,                                                                                                // const VkSpecializationInfo*                  pSpecializationInfo;
381                 }
382         };
383
384         const VkGraphicsPipelineCreateInfo graphicsPipelineInfo =
385         {
386                 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,        // VkStructureType                                                                      sType;
387                 DE_NULL,                                                                                        // const void*                                                                          pNext;
388                 (VkPipelineCreateFlags)0,                                                       // VkPipelineCreateFlags                                                        flags;
389                 DE_LENGTH_OF_ARRAY(pShaderStages),                                      // deUint32                                                                                     stageCount;
390                 pShaderStages,                                                                          // const VkPipelineShaderStageCreateInfo*                       pStages;
391                 &vertexInputStateInfo,                                                          // const VkPipelineVertexInputStateCreateInfo*          pVertexInputState;
392                 &pipelineInputAssemblyStateInfo,                                        // const VkPipelineInputAssemblyStateCreateInfo*        pInputAssemblyState;
393                 DE_NULL,                                                                                        // const VkPipelineTessellationStateCreateInfo*         pTessellationState;
394                 &pipelineViewportStateInfo,                                                     // const VkPipelineViewportStateCreateInfo*                     pViewportState;
395                 &pipelineRasterizationStateInfo,                                        // const VkPipelineRasterizationStateCreateInfo*        pRasterizationState;
396                 &pipelineMultisampleStateInfo,                                          // const VkPipelineMultisampleStateCreateInfo*          pMultisampleState;
397                 &pipelineDepthStencilStateInfo,                                         // const VkPipelineDepthStencilStateCreateInfo*         pDepthStencilState;
398                 &pipelineColorBlendStateInfo,                                           // const VkPipelineColorBlendStateCreateInfo*           pColorBlendState;
399                 DE_NULL,                                                                                        // const VkPipelineDynamicStateCreateInfo*                      pDynamicState;
400                 pipelineLayout,                                                                         // VkPipelineLayout                                                                     layout;
401                 renderPass,                                                                                     // VkRenderPass                                                                         renderPass;
402                 0u,                                                                                                     // deUint32                                                                                     subpass;
403                 DE_NULL,                                                                                        // VkPipeline                                                                           basePipelineHandle;
404                 0,                                                                                                      // deInt32                                                                                      basePipelineIndex;
405         };
406
407         return createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineInfo);
408 }
409
410 VkBufferImageCopy makeBufferImageCopy (const VkImageAspectFlags aspectFlags, const tcu::IVec2& renderSize)
411 {
412         const VkBufferImageCopy copyParams =
413         {
414                 0ull,                                                                                                                   //      VkDeviceSize                            bufferOffset;
415                 0u,                                                                                                                             //      deUint32                                        bufferRowLength;
416                 0u,                                                                                                                             //      deUint32                                        bufferImageHeight;
417                 makeImageSubresourceLayers(aspectFlags, 0u, 0u, 1u),                    //      VkImageSubresourceLayers        imageSubresource;
418                 makeOffset3D(0, 0, 0),                                                                                  //      VkOffset3D                                      imageOffset;
419                 makeExtent3D(renderSize.x(), renderSize.y(), 1u),                               //      VkExtent3D                                      imageExtent;
420         };
421         return copyParams;
422 }
423
424 void commandClearStencilAttachment (const DeviceInterface&      vk,
425                                                                         const VkCommandBuffer   commandBuffer,
426                                                                         const VkOffset2D&               offset,
427                                                                         const VkExtent2D&               extent,
428                                                                         const deUint32                  clearValue)
429 {
430         const VkClearAttachment stencilAttachment =
431         {
432                 VK_IMAGE_ASPECT_STENCIL_BIT,                                    // VkImageAspectFlags    aspectMask;
433                 0u,                                                                                             // uint32_t              colorAttachment;
434                 makeClearValueDepthStencil(0.0f, clearValue),   // VkClearValue          clearValue;
435         };
436
437         const VkClearRect rect =
438         {
439                 { offset, extent },             // VkRect2D    rect;
440                 0u,                                             // uint32_t    baseArrayLayer;
441                 1u,                                             // uint32_t    layerCount;
442         };
443
444         vk.cmdClearAttachments(commandBuffer, 1u, &stencilAttachment, 1u, &rect);
445 }
446
447 VkImageAspectFlags getImageAspectFlags (const VkFormat format)
448 {
449         const tcu::TextureFormat tcuFormat = mapVkFormat(format);
450
451         if      (tcuFormat.order == tcu::TextureFormat::DS)             return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
452         else if (tcuFormat.order == tcu::TextureFormat::D)              return VK_IMAGE_ASPECT_DEPTH_BIT;
453         else if (tcuFormat.order == tcu::TextureFormat::S)              return VK_IMAGE_ASPECT_STENCIL_BIT;
454
455         DE_ASSERT(false);
456         return 0u;
457 }
458
459 bool isSupportedDepthStencilFormat (const InstanceInterface& instanceInterface, const VkPhysicalDevice device, const VkFormat format)
460 {
461         VkFormatProperties formatProps;
462         instanceInterface.getPhysicalDeviceFormatProperties(device, format, &formatProps);
463         return (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0;
464 }
465
466 VkFormat pickSupportedDepthStencilFormat (const InstanceInterface&      instanceInterface,
467                                                                                   const VkPhysicalDevice        device,
468                                                                                   const deUint32                        numFormats,
469                                                                                   const VkFormat*                       pFormats)
470 {
471         for (deUint32 i = 0; i < numFormats; ++i)
472                 if (isSupportedDepthStencilFormat(instanceInterface, device, pFormats[i]))
473                         return pFormats[i];
474         return VK_FORMAT_UNDEFINED;
475 }
476
477 enum Flags
478 {
479         FLAG_TEST_DEPTH                                                 = 1u << 0,
480         FLAG_TEST_STENCIL                                               = 1u << 1,
481         FLAG_DONT_USE_TEST_ATTACHMENT                   = 1u << 2,
482         FLAG_DONT_USE_EARLY_FRAGMENT_TESTS              = 1u << 3,
483 };
484
485 class EarlyFragmentTest : public TestCase
486 {
487 public:
488                                                 EarlyFragmentTest       (tcu::TestContext&              testCtx,
489                                                                                          const std::string              name,
490                                                                                          const deUint32                 flags);
491
492         void                            initPrograms            (SourceCollections&             programCollection) const;
493         TestInstance*           createInstance          (Context&                               context) const;
494
495 private:
496         const deUint32          m_flags;
497 };
498
499 EarlyFragmentTest::EarlyFragmentTest (tcu::TestContext& testCtx, const std::string name, const deUint32 flags)
500         : TestCase      (testCtx, name, "")
501         , m_flags       (flags)
502 {
503 }
504
505 void EarlyFragmentTest::initPrograms (SourceCollections& programCollection) const
506 {
507         // Vertex
508         {
509                 std::ostringstream src;
510                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
511                         << "\n"
512                         << "layout(location = 0) in highp vec4 position;\n"
513                         << "\n"
514                         << "out gl_PerVertex {\n"
515                         << "   vec4 gl_Position;\n"
516                         << "};\n"
517                         << "\n"
518                         << "void main (void)\n"
519                         << "{\n"
520                         << "    gl_Position = position;\n"
521                         << "}\n";
522
523                 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
524         }
525
526         // Fragment
527         {
528                 const bool useEarlyTests = (m_flags & FLAG_DONT_USE_EARLY_FRAGMENT_TESTS) == 0;
529                 std::ostringstream src;
530                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
531                         << "\n"
532                         << (useEarlyTests ? "layout(early_fragment_tests) in;\n" : "")
533                         << "layout(location = 0) out highp vec4 fragColor;\n"
534                         << "\n"
535                         << "layout(binding = 0) coherent buffer Output {\n"
536                         << "    uint result;\n"
537                         << "} sb_out;\n"
538                         << "\n"
539                         << "void main (void)\n"
540                         << "{\n"
541                         << "    atomicAdd(sb_out.result, 1u);\n"
542                         << "    fragColor = vec4(1.0, 1.0, 0.0, 1.0);\n"
543                         << "}\n";
544
545                 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
546         }
547 }
548
549 class EarlyFragmentTestInstance : public TestInstance
550 {
551 public:
552                                                         EarlyFragmentTestInstance (Context& context, const deUint32 flags);
553
554         tcu::TestStatus                 iterate                                   (void);
555
556 private:
557         enum TestMode
558         {
559                 MODE_INVALID,
560                 MODE_DEPTH,
561                 MODE_STENCIL,
562         };
563
564         const TestMode                  m_testMode;
565         const bool                              m_useTestAttachment;
566         const bool                              m_useEarlyTests;
567 };
568
569 EarlyFragmentTestInstance::EarlyFragmentTestInstance (Context& context, const deUint32 flags)
570         : TestInstance                  (context)
571         , m_testMode                    (flags & FLAG_TEST_DEPTH   ? MODE_DEPTH :
572                                                          flags & FLAG_TEST_STENCIL ? MODE_STENCIL : MODE_INVALID)
573         , m_useTestAttachment   ((flags & FLAG_DONT_USE_TEST_ATTACHMENT) == 0)
574         , m_useEarlyTests               ((flags & FLAG_DONT_USE_EARLY_FRAGMENT_TESTS) == 0)
575 {
576         DE_ASSERT(m_testMode != MODE_INVALID);
577 }
578
579 tcu::TestStatus EarlyFragmentTestInstance::iterate (void)
580 {
581         const DeviceInterface&          vk                                      = m_context.getDeviceInterface();
582         const InstanceInterface&        vki                                     = m_context.getInstanceInterface();
583         const VkDevice                          device                          = m_context.getDevice();
584         const VkPhysicalDevice          physDevice                      = m_context.getPhysicalDevice();
585         const VkQueue                           queue                           = m_context.getUniversalQueue();
586         const deUint32                          queueFamilyIndex        = m_context.getUniversalQueueFamilyIndex();
587         Allocator&                                      allocator                       = m_context.getDefaultAllocator();
588
589         // Color attachment
590
591         const tcu::IVec2                                renderSize                      = tcu::IVec2(32, 32);
592         const VkFormat                                  colorFormat                     = VK_FORMAT_R8G8B8A8_UNORM;
593         const VkImageSubresourceRange   colorSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
594         const Unique<VkImage>                   colorImage                      (makeImage(vk, device, makeImageCreateInfo(renderSize, colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
595         const UniquePtr<Allocation>             colorImageAlloc         (bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any));
596         const Unique<VkImageView>               colorImageView          (makeImageView(vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange));
597
598         // Test attachment (depth or stencil)
599         static const VkFormat stencilFormats[] =
600         {
601                 // One of the following formats must be supported, as per spec requirement.
602                 VK_FORMAT_S8_UINT,
603                 VK_FORMAT_D16_UNORM_S8_UINT,
604                 VK_FORMAT_D24_UNORM_S8_UINT,
605                 VK_FORMAT_D32_SFLOAT_S8_UINT,
606         };
607
608         const VkFormat testFormat = (m_testMode == MODE_STENCIL ? pickSupportedDepthStencilFormat(vki, physDevice, DE_LENGTH_OF_ARRAY(stencilFormats), stencilFormats)
609                                                                                                                         : VK_FORMAT_D16_UNORM);         // spec requires this format to be supported
610         if (testFormat == VK_FORMAT_UNDEFINED)
611                 return tcu::TestStatus::fail("Required depth/stencil format not supported");
612
613         if (m_useTestAttachment)
614                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Using depth/stencil format " << getFormatName(testFormat) << tcu::TestLog::EndMessage;
615
616         const VkImageSubresourceRange   testSubresourceRange    = makeImageSubresourceRange(getImageAspectFlags(testFormat), 0u, 1u, 0u, 1u);
617         const Unique<VkImage>                   testImage                               (makeImage(vk, device, makeImageCreateInfo(renderSize, testFormat, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)));
618         const UniquePtr<Allocation>             testImageAlloc                  (bindImage(vk, device, allocator, *testImage, MemoryRequirement::Any));
619         const Unique<VkImageView>               testImageView                   (makeImageView(vk, device, *testImage, VK_IMAGE_VIEW_TYPE_2D, testFormat, testSubresourceRange));
620         const VkImageView                               attachmentImages[]              = { *colorImageView, *testImageView };
621         const deUint32                                  numUsedAttachmentImages = (m_useTestAttachment ? 2u : 1u);
622
623         // Vertex buffer
624
625         const deUint32                                  numVertices                             = 6;
626         const VkDeviceSize                              vertexBufferSizeBytes   = sizeof(tcu::Vec4) * numVertices;
627         const Unique<VkBuffer>                  vertexBuffer                    (makeBuffer(vk, device, makeBufferCreateInfo(vertexBufferSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT)));
628         const UniquePtr<Allocation>             vertexBufferAlloc               (bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible));
629
630         {
631                 tcu::Vec4* const pVertices = reinterpret_cast<tcu::Vec4*>(vertexBufferAlloc->getHostPtr());
632
633                 pVertices[0] = tcu::Vec4( 1.0f, -1.0f,  0.5f,  1.0f);
634                 pVertices[1] = tcu::Vec4(-1.0f, -1.0f,  0.0f,  1.0f);
635                 pVertices[2] = tcu::Vec4(-1.0f,  1.0f,  0.5f,  1.0f);
636
637                 pVertices[3] = tcu::Vec4(-1.0f,  1.0f,  0.5f,  1.0f);
638                 pVertices[4] = tcu::Vec4( 1.0f,  1.0f,  1.0f,  1.0f);
639                 pVertices[5] = tcu::Vec4( 1.0f, -1.0f,  0.5f,  1.0f);
640
641                 flushMappedMemoryRange(vk, device, vertexBufferAlloc->getMemory(), vertexBufferAlloc->getOffset(), vertexBufferSizeBytes);
642                 // No barrier needed, flushed memory is automatically visible
643         }
644
645         // Result buffer
646
647         const VkDeviceSize                              resultBufferSizeBytes   = sizeof(deUint32);
648         const Unique<VkBuffer>                  resultBuffer                    (makeBuffer(vk, device, makeBufferCreateInfo(resultBufferSizeBytes, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT)));
649         const UniquePtr<Allocation>             resultBufferAlloc               (bindBuffer(vk, device, allocator, *resultBuffer, MemoryRequirement::HostVisible));
650
651         {
652                 deUint32* const pData = static_cast<deUint32*>(resultBufferAlloc->getHostPtr());
653
654                 *pData = 0;
655                 flushMappedMemoryRange(vk, device, resultBufferAlloc->getMemory(), resultBufferAlloc->getOffset(), resultBufferSizeBytes);
656         }
657
658         // Render result buffer (to retrieve color attachment contents)
659
660         const VkDeviceSize                              colorBufferSizeBytes    = tcu::getPixelSize(mapVkFormat(colorFormat)) * renderSize.x() * renderSize.y();
661         const Unique<VkBuffer>                  colorBuffer                             (makeBuffer(vk, device, makeBufferCreateInfo(colorBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT)));
662         const UniquePtr<Allocation>             colorBufferAlloc                (bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
663
664         // Descriptors
665
666         const Unique<VkDescriptorSetLayout> descriptorSetLayout(DescriptorSetLayoutBuilder()
667                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT)
668                 .build(vk, device));
669
670         const Unique<VkDescriptorPool> descriptorPool(DescriptorPoolBuilder()
671                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
672                 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
673
674         const Unique<VkDescriptorSet> descriptorSet                              (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
675         const VkDescriptorBufferInfo  resultBufferDescriptorInfo = makeDescriptorBufferInfo(resultBuffer.get(), 0ull, resultBufferSizeBytes);
676
677         DescriptorSetUpdateBuilder()
678                 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultBufferDescriptorInfo)
679                 .update(vk, device);
680
681         // Pipeline
682
683         const Unique<VkShaderModule>    vertexModule  (createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
684         const Unique<VkShaderModule>    fragmentModule(createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u));
685         const Unique<VkRenderPass>              renderPass        (makeRenderPass(vk, device, colorFormat, m_useTestAttachment, testFormat));
686         const Unique<VkFramebuffer>             framebuffer       (makeFramebuffer(vk, device, *renderPass, numUsedAttachmentImages, attachmentImages, renderSize));
687         const Unique<VkPipelineLayout>  pipelineLayout(makePipelineLayout(vk, device, *descriptorSetLayout));
688         const Unique<VkPipeline>                pipeline          (makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule, renderSize,
689                                                                                                   (m_testMode == MODE_DEPTH), (m_testMode == MODE_STENCIL)));
690         const Unique<VkCommandPool>             cmdPool           (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
691         const Unique<VkCommandBuffer>   cmdBuffer         (allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
692
693         // Draw commands
694
695         {
696                 const VkRect2D renderArea = {
697                         makeOffset2D(0, 0),
698                         makeExtent2D(renderSize.x(), renderSize.y()),
699                 };
700                 const tcu::Vec4 clearColor(0.0f, 0.0f, 0.0f, 1.0f);
701                 const VkDeviceSize vertexBufferOffset = 0ull;
702
703                 beginCommandBuffer(vk, *cmdBuffer);
704
705                 {
706                         const VkImageMemoryBarrier barriers[] = {
707                                 makeImageMemoryBarrier(
708                                         0u, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
709                                         VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
710                                         *colorImage, colorSubresourceRange),
711                                 makeImageMemoryBarrier(
712                                         0u, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
713                                         VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
714                                         *testImage, testSubresourceRange),
715                         };
716
717                         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u,
718                                 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
719                 }
720
721                 // Will clear the attachments with specified depth and stencil values.
722                 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea, clearColor, 0.5f, 0u);
723
724                 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
725                 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
726                 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
727
728                 // Mask half of the attachment image with value that will pass the stencil test.
729                 if (m_useTestAttachment && m_testMode == MODE_STENCIL)
730                         commandClearStencilAttachment(vk, *cmdBuffer, makeOffset2D(0, 0), makeExtent2D(renderSize.x()/2, renderSize.y()), 1u);
731
732                 vk.cmdDraw(*cmdBuffer, numVertices, 1u, 0u, 0u);
733                 vk.cmdEndRenderPass(*cmdBuffer);
734
735                 {
736                         const VkBufferMemoryBarrier shaderWriteBarrier = makeBufferMemoryBarrier(
737                                 VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *resultBuffer, 0ull, resultBufferSizeBytes);
738
739                         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
740                                 0u, DE_NULL, 1u, &shaderWriteBarrier, 0u, DE_NULL);
741
742                         const VkImageMemoryBarrier preCopyColorImageBarrier = makeImageMemoryBarrier(
743                                 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
744                                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
745                                 *colorImage, colorSubresourceRange);
746
747                         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
748                                 0u, DE_NULL, 0u, DE_NULL, 1u, &preCopyColorImageBarrier);
749
750                         const VkBufferImageCopy copyRegion = makeBufferImageCopy(VK_IMAGE_ASPECT_COLOR_BIT, renderSize);
751                         vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, &copyRegion);
752
753                         const VkBufferMemoryBarrier postCopyColorBufferBarrier = makeBufferMemoryBarrier(
754                                 VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *colorBuffer, 0ull, colorBufferSizeBytes);
755
756                         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
757                                 0u, DE_NULL, 1u, &postCopyColorBufferBarrier, 0u, DE_NULL);
758                 }
759
760                 VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
761                 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
762         }
763
764         // Log result image
765         {
766                 invalidateMappedMemoryRange(vk, device, colorBufferAlloc->getMemory(), colorBufferAlloc->getOffset(), colorBufferSizeBytes);
767
768                 const tcu::ConstPixelBufferAccess imagePixelAccess(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1, colorBufferAlloc->getHostPtr());
769
770                 tcu::TestLog& log = m_context.getTestContext().getLog();
771                 log << tcu::TestLog::Image("color0", "Rendered image", imagePixelAccess);
772         }
773
774         // Verify results
775         {
776                 invalidateMappedMemoryRange(vk, device, resultBufferAlloc->getMemory(), resultBufferAlloc->getOffset(), resultBufferSizeBytes);
777
778                 const int  actualCounter           = *static_cast<deInt32*>(resultBufferAlloc->getHostPtr());
779                 const bool expectPartialResult = (m_useEarlyTests && m_useTestAttachment);
780                 const int  expectedCounter         = expectPartialResult ? renderSize.x() * renderSize.y() / 2 : renderSize.x() * renderSize.y();
781                 const int  tolerance               = expectPartialResult ? de::max(renderSize.x(), renderSize.y()) * 3  : 0;
782                 const int  expectedMin         = de::max(0, expectedCounter - tolerance);
783                 const int  expectedMax             = expectedCounter + tolerance;
784
785                 tcu::TestLog& log = m_context.getTestContext().getLog();
786                 log << tcu::TestLog::Message << "Expected value"
787                         << (expectPartialResult ? " in range: [" + de::toString(expectedMin) + ", " + de::toString(expectedMax) + "]" : ": " + de::toString(expectedCounter))
788                         << tcu::TestLog::EndMessage;
789                 log << tcu::TestLog::Message << "Result value: " << de::toString(actualCounter) << tcu::TestLog::EndMessage;
790
791                 if (expectedMin <= actualCounter && actualCounter <= expectedMax)
792                         return tcu::TestStatus::pass("Success");
793                 else
794                         return tcu::TestStatus::fail("Value out of range");
795         }
796 }
797
798 TestInstance* EarlyFragmentTest::createInstance (Context& context) const
799 {
800         // Check required features
801         {
802                 VkPhysicalDeviceFeatures features;
803                 context.getInstanceInterface().getPhysicalDeviceFeatures(context.getPhysicalDevice(), &features);
804
805                 // SSBO writes in fragment shader
806                 if (!features.fragmentStoresAndAtomics)
807                         throw tcu::NotSupportedError("Missing required feature: fragmentStoresAndAtomics");
808         }
809
810         return new EarlyFragmentTestInstance(context, m_flags);
811 }
812
813 } // anonymous ns
814
815 tcu::TestCaseGroup* createEarlyFragmentTests (tcu::TestContext& testCtx)
816 {
817         de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "early_fragment", "early fragment test cases"));
818
819         static const struct
820         {
821                 std::string caseName;
822                 deUint32        flags;
823         } cases[] =
824         {
825                 { "no_early_fragment_tests_depth",                                      FLAG_TEST_DEPTH   | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS                                                                  },
826                 { "no_early_fragment_tests_stencil",                            FLAG_TEST_STENCIL | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS                                                                  },
827                 { "early_fragment_tests_depth",                                         FLAG_TEST_DEPTH                                                                                                                                                 },
828                 { "early_fragment_tests_stencil",                                       FLAG_TEST_STENCIL                                                                                                                                               },
829                 { "no_early_fragment_tests_depth_no_attachment",        FLAG_TEST_DEPTH   | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS | FLAG_DONT_USE_TEST_ATTACHMENT  },
830                 { "no_early_fragment_tests_stencil_no_attachment",      FLAG_TEST_STENCIL | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS | FLAG_DONT_USE_TEST_ATTACHMENT  },
831                 { "early_fragment_tests_depth_no_attachment",           FLAG_TEST_DEPTH   |                                                                              FLAG_DONT_USE_TEST_ATTACHMENT  },
832                 { "early_fragment_tests_stencil_no_attachment",         FLAG_TEST_STENCIL |                                                                              FLAG_DONT_USE_TEST_ATTACHMENT  },
833         };
834
835         for (int i = 0; i < DE_LENGTH_OF_ARRAY(cases); ++i)
836                 testGroup->addChild(new EarlyFragmentTest(testCtx, cases[i].caseName, cases[i].flags));
837
838         return testGroup.release();
839 }
840
841 } // FragmentOperations
842 } // vkt