Merge pull request #276 from Ella-0/master
[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 #include "vkBarrierUtil.hpp"
41 #include "vkCmdUtil.hpp"
42 #include "vkObjUtil.hpp"
43
44 #include "tcuTestLog.hpp"
45 #include "tcuImageCompare.hpp"
46 #include "tcuTextureUtil.hpp"
47
48 #include "deUniquePtr.hpp"
49 #include "deStringUtil.hpp"
50 #include "deMath.h"
51
52 #include <string>
53
54 namespace vkt
55 {
56 namespace FragmentOperations
57 {
58 namespace
59 {
60 using namespace vk;
61 using de::UniquePtr;
62
63 //! Basic 2D image.
64 inline VkImageCreateInfo makeImageCreateInfo (const tcu::IVec2& size, const VkFormat format, const VkImageUsageFlags usage)
65 {
66         const VkImageCreateInfo imageParams =
67         {
68                 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                                    // VkStructureType                      sType;
69                 DE_NULL,                                                                                                // const void*                          pNext;
70                 (VkImageCreateFlags)0,                                                                  // VkImageCreateFlags           flags;
71                 VK_IMAGE_TYPE_2D,                                                                               // VkImageType                          imageType;
72                 format,                                                                                                 // VkFormat                                     format;
73                 makeExtent3D(size.x(), size.y(), 1),                                    // VkExtent3D                           extent;
74                 1u,                                                                                                             // deUint32                                     mipLevels;
75                 1u,                                                                                                             // deUint32                                     arrayLayers;
76                 VK_SAMPLE_COUNT_1_BIT,                                                                  // VkSampleCountFlagBits        samples;
77                 VK_IMAGE_TILING_OPTIMAL,                                                                // VkImageTiling                        tiling;
78                 usage,                                                                                                  // VkImageUsageFlags            usage;
79                 VK_SHARING_MODE_EXCLUSIVE,                                                              // VkSharingMode                        sharingMode;
80                 0u,                                                                                                             // deUint32                                     queueFamilyIndexCount;
81                 DE_NULL,                                                                                                // const deUint32*                      pQueueFamilyIndices;
82                 VK_IMAGE_LAYOUT_UNDEFINED,                                                              // VkImageLayout                        initialLayout;
83         };
84         return imageParams;
85 }
86
87 Move<VkRenderPass> makeRenderPass (const DeviceInterface&       vk,
88                                                                    const VkDevice                       device,
89                                                                    const VkFormat                       colorFormat,
90                                                                    const bool                           useDepthStencilAttachment,
91                                                                    const VkFormat                       depthStencilFormat)
92 {
93         return makeRenderPass(vk, device, colorFormat, useDepthStencilAttachment ? depthStencilFormat : VK_FORMAT_UNDEFINED);
94 }
95
96 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface&   vk,
97                                                                            const VkDevice                       device,
98                                                                            const VkPipelineLayout       pipelineLayout,
99                                                                            const VkRenderPass           renderPass,
100                                                                            const VkShaderModule         vertexModule,
101                                                                            const VkShaderModule         fragmentModule,
102                                                                            const tcu::IVec2&            renderSize,
103                                                                            const bool                           enableDepthTest,
104                                                                            const bool                           enableStencilTest,
105                                                                            const VkStencilOp            stencilFailOp = VK_STENCIL_OP_KEEP,
106                                                                            const VkStencilOp            stencilPassOp = VK_STENCIL_OP_KEEP)
107 {
108         const std::vector<VkViewport>                   viewports                                       (1, makeViewport(renderSize));
109         const std::vector<VkRect2D>                             scissors                                        (1, makeRect2D(renderSize));
110
111         const VkStencilOpState                                  stencilOpState                          = makeStencilOpState(
112                 stencilFailOp,                  // stencil fail
113             stencilPassOp,                      // depth & stencil pass
114                 VK_STENCIL_OP_KEEP,             // depth only fail
115                 VK_COMPARE_OP_EQUAL,    // compare op
116                 0x3,                                    // compare mask
117                 0xf,                                    // write mask
118                 1u);                                    // reference
119
120         VkPipelineDepthStencilStateCreateInfo   depthStencilStateCreateInfo     =
121         {
122                 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,     // VkStructureType                          sType
123                 DE_NULL,                                                                                                        // const void*                              pNext
124                 0u,                                                                                                                     // VkPipelineDepthStencilStateCreateFlags   flags
125                 enableDepthTest ? VK_TRUE : VK_FALSE,                                           // VkBool32                                 depthTestEnable
126                 enableDepthTest ? VK_TRUE : VK_FALSE,                                           // VkBool32                                 depthWriteEnable
127                 VK_COMPARE_OP_LESS,                                                                                     // VkCompareOp                              depthCompareOp
128                 VK_FALSE,                                                                                                       // VkBool32                                 depthBoundsTestEnable
129                 enableStencilTest ? VK_TRUE : VK_FALSE,                                         // VkBool32                                 stencilTestEnable
130                 stencilOpState,                                                                                         // VkStencilOpState                         front
131                 stencilOpState,                                                                                         // VkStencilOpState                         back
132                 0.0f,                                                                                                           // float                                    minDepthBounds
133                 1.0f                                                                                                            // float                                    maxDepthBounds
134         };
135
136         return vk::makeGraphicsPipeline(vk,                                                                             // const DeviceInterface&                        vk
137                                                                         device,                                                                 // const VkDevice                                device
138                                                                         pipelineLayout,                                                 // const VkPipelineLayout                        pipelineLayout
139                                                                         vertexModule,                                                   // const VkShaderModule                          vertexShaderModule
140                                                                         DE_NULL,                                                                // const VkShaderModule                          tessellationControlModule
141                                                                         DE_NULL,                                                                // const VkShaderModule                          tessellationEvalModule
142                                                                         DE_NULL,                                                                // const VkShaderModule                          geometryShaderModule
143                                                                         fragmentModule,                                                 // const VkShaderModule                          fragmentShaderModule
144                                                                         renderPass,                                                             // const VkRenderPass                            renderPass
145                                                                         viewports,                                                              // const std::vector<VkViewport>&                viewports
146                                                                         scissors,                                                               // const std::vector<VkRect2D>&                  scissors
147                                                                         VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,    // const VkPrimitiveTopology                     topology
148                                                                         0u,                                                                             // const deUint32                                subpass
149                                                                         0u,                                                                             // const deUint32                                patchControlPoints
150                                                                         DE_NULL,                                                                // const VkPipelineVertexInputStateCreateInfo*   vertexInputStateCreateInfo
151                                                                         DE_NULL,                                                                // const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
152                                                                         DE_NULL,                                                                // const VkPipelineMultisampleStateCreateInfo*   multisampleStateCreateInfo
153                                                                         &depthStencilStateCreateInfo);                  // const VkPipelineDepthStencilStateCreateInfo*  depthStencilStateCreateInfo
154 }
155
156 void commandClearStencilAttachment (const DeviceInterface&      vk,
157                                                                         const VkCommandBuffer   commandBuffer,
158                                                                         const VkOffset2D&               offset,
159                                                                         const VkExtent2D&               extent,
160                                                                         const deUint32                  clearValue)
161 {
162         const VkClearAttachment stencilAttachment =
163         {
164                 VK_IMAGE_ASPECT_STENCIL_BIT,                                    // VkImageAspectFlags    aspectMask;
165                 0u,                                                                                             // uint32_t              colorAttachment;
166                 makeClearValueDepthStencil(0.0f, clearValue),   // VkClearValue          clearValue;
167         };
168
169         const VkClearRect rect =
170         {
171                 { offset, extent },             // VkRect2D    rect;
172                 0u,                                             // uint32_t    baseArrayLayer;
173                 1u,                                             // uint32_t    layerCount;
174         };
175
176         vk.cmdClearAttachments(commandBuffer, 1u, &stencilAttachment, 1u, &rect);
177 }
178
179 VkImageAspectFlags getImageAspectFlags (const VkFormat format)
180 {
181         const tcu::TextureFormat tcuFormat = mapVkFormat(format);
182
183         if      (tcuFormat.order == tcu::TextureFormat::DS)             return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
184         else if (tcuFormat.order == tcu::TextureFormat::D)              return VK_IMAGE_ASPECT_DEPTH_BIT;
185         else if (tcuFormat.order == tcu::TextureFormat::S)              return VK_IMAGE_ASPECT_STENCIL_BIT;
186
187         DE_ASSERT(false);
188         return 0u;
189 }
190
191 bool isSupportedDepthStencilFormat (const InstanceInterface& instanceInterface, const VkPhysicalDevice device, const VkFormat format)
192 {
193         VkFormatProperties formatProps;
194         instanceInterface.getPhysicalDeviceFormatProperties(device, format, &formatProps);
195         return (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0;
196 }
197
198 VkFormat pickSupportedDepthStencilFormat (const InstanceInterface&      instanceInterface,
199                                                                                   const VkPhysicalDevice        device,
200                                                                                   const deUint32                        numFormats,
201                                                                                   const VkFormat*                       pFormats)
202 {
203         for (deUint32 i = 0; i < numFormats; ++i)
204                 if (isSupportedDepthStencilFormat(instanceInterface, device, pFormats[i]))
205                         return pFormats[i];
206         return VK_FORMAT_UNDEFINED;
207 }
208
209 enum Flags
210 {
211         FLAG_TEST_DEPTH                                                 = 1u << 0,
212         FLAG_TEST_STENCIL                                               = 1u << 1,
213         FLAG_DONT_USE_TEST_ATTACHMENT                   = 1u << 2,
214         FLAG_DONT_USE_EARLY_FRAGMENT_TESTS              = 1u << 3,
215 };
216
217 class EarlyFragmentTest : public TestCase
218 {
219 public:
220                                                 EarlyFragmentTest       (tcu::TestContext&              testCtx,
221                                                                                          const std::string              name,
222                                                                                          const deUint32                 flags);
223
224         void                            initPrograms            (SourceCollections&             programCollection) const;
225         TestInstance*           createInstance          (Context&                               context) const;
226         virtual void            checkSupport            (Context&                               context) const;
227
228 private:
229         const deUint32          m_flags;
230 };
231
232 EarlyFragmentTest::EarlyFragmentTest (tcu::TestContext& testCtx, const std::string name, const deUint32 flags)
233         : TestCase      (testCtx, name, "")
234         , m_flags       (flags)
235 {
236 }
237
238 void EarlyFragmentTest::initPrograms (SourceCollections& programCollection) const
239 {
240         // Vertex
241         {
242                 std::ostringstream src;
243                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
244                         << "\n"
245                         << "layout(location = 0) in highp vec4 position;\n"
246                         << "\n"
247                         << "out gl_PerVertex {\n"
248                         << "   vec4 gl_Position;\n"
249                         << "};\n"
250                         << "\n"
251                         << "void main (void)\n"
252                         << "{\n"
253                         << "    gl_Position = position;\n"
254                         << "}\n";
255
256                 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
257         }
258
259         // Fragment
260         {
261                 const bool useEarlyTests = (m_flags & FLAG_DONT_USE_EARLY_FRAGMENT_TESTS) == 0;
262                 std::ostringstream src;
263                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
264                         << "\n"
265                         << (useEarlyTests ? "layout(early_fragment_tests) in;\n" : "")
266                         << "layout(location = 0) out highp vec4 fragColor;\n"
267                         << "\n"
268                         << "layout(binding = 0) coherent buffer Output {\n"
269                         << "    uint result;\n"
270                         << "} sb_out;\n"
271                         << "\n"
272                         << "void main (void)\n"
273                         << "{\n"
274                         << "    atomicAdd(sb_out.result, 1u);\n"
275                         << "    fragColor = vec4(1.0, 1.0, 0.0, 1.0);\n"
276                         << "}\n";
277
278                 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
279         }
280 }
281
282 class EarlyFragmentTestInstance : public TestInstance
283 {
284 public:
285                                                         EarlyFragmentTestInstance (Context& context, const deUint32 flags);
286
287         tcu::TestStatus                 iterate                                   (void);
288
289 private:
290         enum TestMode
291         {
292                 MODE_INVALID,
293                 MODE_DEPTH,
294                 MODE_STENCIL,
295         };
296
297         const TestMode                  m_testMode;
298         const bool                              m_useTestAttachment;
299         const bool                              m_useEarlyTests;
300 };
301
302 EarlyFragmentTestInstance::EarlyFragmentTestInstance (Context& context, const deUint32 flags)
303         : TestInstance                  (context)
304         , m_testMode                    (flags & FLAG_TEST_DEPTH   ? MODE_DEPTH :
305                                                          flags & FLAG_TEST_STENCIL ? MODE_STENCIL : MODE_INVALID)
306         , m_useTestAttachment   ((flags & FLAG_DONT_USE_TEST_ATTACHMENT) == 0)
307         , m_useEarlyTests               ((flags & FLAG_DONT_USE_EARLY_FRAGMENT_TESTS) == 0)
308 {
309         DE_ASSERT(m_testMode != MODE_INVALID);
310 }
311
312 tcu::TestStatus EarlyFragmentTestInstance::iterate (void)
313 {
314         const DeviceInterface&          vk                                      = m_context.getDeviceInterface();
315         const InstanceInterface&        vki                                     = m_context.getInstanceInterface();
316         const VkDevice                          device                          = m_context.getDevice();
317         const VkPhysicalDevice          physDevice                      = m_context.getPhysicalDevice();
318         const VkQueue                           queue                           = m_context.getUniversalQueue();
319         const deUint32                          queueFamilyIndex        = m_context.getUniversalQueueFamilyIndex();
320         Allocator&                                      allocator                       = m_context.getDefaultAllocator();
321
322         // Color attachment
323
324         const tcu::IVec2                                renderSize                      = tcu::IVec2(32, 32);
325         const VkFormat                                  colorFormat                     = VK_FORMAT_R8G8B8A8_UNORM;
326         const VkImageSubresourceRange   colorSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
327         const Unique<VkImage>                   colorImage                      (makeImage(vk, device, makeImageCreateInfo(renderSize, colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
328         const UniquePtr<Allocation>             colorImageAlloc         (bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any));
329         const Unique<VkImageView>               colorImageView          (makeImageView(vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange));
330
331         // Test attachment (depth or stencil)
332         static const VkFormat stencilFormats[] =
333         {
334                 // One of the following formats must be supported, as per spec requirement.
335                 VK_FORMAT_S8_UINT,
336                 VK_FORMAT_D16_UNORM_S8_UINT,
337                 VK_FORMAT_D24_UNORM_S8_UINT,
338                 VK_FORMAT_D32_SFLOAT_S8_UINT,
339         };
340
341         const VkFormat testFormat = (m_testMode == MODE_STENCIL ? pickSupportedDepthStencilFormat(vki, physDevice, DE_LENGTH_OF_ARRAY(stencilFormats), stencilFormats)
342                                                                                                                         : VK_FORMAT_D16_UNORM);         // spec requires this format to be supported
343         if (testFormat == VK_FORMAT_UNDEFINED)
344                 return tcu::TestStatus::fail("Required depth/stencil format not supported");
345
346         if (m_useTestAttachment)
347                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Using depth/stencil format " << getFormatName(testFormat) << tcu::TestLog::EndMessage;
348
349         const VkImageSubresourceRange   testSubresourceRange    = makeImageSubresourceRange(getImageAspectFlags(testFormat), 0u, 1u, 0u, 1u);
350         const Unique<VkImage>                   testImage                               (makeImage(vk, device, makeImageCreateInfo(renderSize, testFormat, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)));
351         const UniquePtr<Allocation>             testImageAlloc                  (bindImage(vk, device, allocator, *testImage, MemoryRequirement::Any));
352         const Unique<VkImageView>               testImageView                   (makeImageView(vk, device, *testImage, VK_IMAGE_VIEW_TYPE_2D, testFormat, testSubresourceRange));
353         const VkImageView                               attachmentImages[]              = { *colorImageView, *testImageView };
354         const deUint32                                  numUsedAttachmentImages = (m_useTestAttachment ? 2u : 1u);
355
356         // Vertex buffer
357
358         const deUint32                                  numVertices                             = 6;
359         const VkDeviceSize                              vertexBufferSizeBytes   = sizeof(tcu::Vec4) * numVertices;
360         const Unique<VkBuffer>                  vertexBuffer                    (makeBuffer(vk, device, vertexBufferSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
361         const UniquePtr<Allocation>             vertexBufferAlloc               (bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible));
362
363         {
364                 tcu::Vec4* const pVertices = reinterpret_cast<tcu::Vec4*>(vertexBufferAlloc->getHostPtr());
365
366                 pVertices[0] = tcu::Vec4( 1.0f, -1.0f,  0.5f,  1.0f);
367                 pVertices[1] = tcu::Vec4(-1.0f, -1.0f,  0.0f,  1.0f);
368                 pVertices[2] = tcu::Vec4(-1.0f,  1.0f,  0.5f,  1.0f);
369
370                 pVertices[3] = tcu::Vec4(-1.0f,  1.0f,  0.5f,  1.0f);
371                 pVertices[4] = tcu::Vec4( 1.0f,  1.0f,  1.0f,  1.0f);
372                 pVertices[5] = tcu::Vec4( 1.0f, -1.0f,  0.5f,  1.0f);
373
374                 flushAlloc(vk, device, *vertexBufferAlloc);
375                 // No barrier needed, flushed memory is automatically visible
376         }
377
378         // Result buffer
379
380         const VkDeviceSize                              resultBufferSizeBytes   = sizeof(deUint32);
381         const Unique<VkBuffer>                  resultBuffer                    (makeBuffer(vk, device, resultBufferSizeBytes, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT));
382         const UniquePtr<Allocation>             resultBufferAlloc               (bindBuffer(vk, device, allocator, *resultBuffer, MemoryRequirement::HostVisible));
383
384         {
385                 deUint32* const pData = static_cast<deUint32*>(resultBufferAlloc->getHostPtr());
386
387                 *pData = 0;
388                 flushAlloc(vk, device, *resultBufferAlloc);
389         }
390
391         // Render result buffer (to retrieve color attachment contents)
392
393         const VkDeviceSize                              colorBufferSizeBytes    = tcu::getPixelSize(mapVkFormat(colorFormat)) * renderSize.x() * renderSize.y();
394         const Unique<VkBuffer>                  colorBuffer                             (makeBuffer(vk, device, colorBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
395         const UniquePtr<Allocation>             colorBufferAlloc                (bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
396
397         // Descriptors
398
399         const Unique<VkDescriptorSetLayout> descriptorSetLayout(DescriptorSetLayoutBuilder()
400                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT)
401                 .build(vk, device));
402
403         const Unique<VkDescriptorPool> descriptorPool(DescriptorPoolBuilder()
404                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
405                 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
406
407         const Unique<VkDescriptorSet> descriptorSet                              (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
408         const VkDescriptorBufferInfo  resultBufferDescriptorInfo = makeDescriptorBufferInfo(resultBuffer.get(), 0ull, resultBufferSizeBytes);
409
410         DescriptorSetUpdateBuilder()
411                 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultBufferDescriptorInfo)
412                 .update(vk, device);
413
414         // Pipeline
415
416         const Unique<VkShaderModule>    vertexModule  (createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
417         const Unique<VkShaderModule>    fragmentModule(createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u));
418         const Unique<VkRenderPass>              renderPass        (makeRenderPass(vk, device, colorFormat, m_useTestAttachment, testFormat));
419         const Unique<VkFramebuffer>             framebuffer       (makeFramebuffer(vk, device, *renderPass, numUsedAttachmentImages, attachmentImages, renderSize.x(), renderSize.y()));
420         const Unique<VkPipelineLayout>  pipelineLayout(makePipelineLayout(vk, device, *descriptorSetLayout));
421         const Unique<VkPipeline>                pipeline          (makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule, renderSize,
422                                                                                                   (m_testMode == MODE_DEPTH), (m_testMode == MODE_STENCIL)));
423         const Unique<VkCommandPool>             cmdPool           (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
424         const Unique<VkCommandBuffer>   cmdBuffer         (allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
425
426         // Draw commands
427
428         {
429                 const VkRect2D renderArea = {
430                         makeOffset2D(0, 0),
431                         makeExtent2D(renderSize.x(), renderSize.y()),
432                 };
433                 const tcu::Vec4 clearColor(0.0f, 0.0f, 0.0f, 1.0f);
434                 const VkDeviceSize vertexBufferOffset = 0ull;
435
436                 beginCommandBuffer(vk, *cmdBuffer);
437
438                 {
439                         const VkImageMemoryBarrier barriers[] = {
440                                 makeImageMemoryBarrier(
441                                         0u, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
442                                         VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
443                                         *colorImage, colorSubresourceRange),
444                                 makeImageMemoryBarrier(
445                                         0u, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
446                                         VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
447                                         *testImage, testSubresourceRange),
448                         };
449
450                         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u,
451                                 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
452                 }
453
454                 // Will clear the attachments with specified depth and stencil values.
455                 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea, clearColor, 0.5f, 0u);
456
457                 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
458                 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
459                 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
460
461                 // Mask half of the attachment image with value that will pass the stencil test.
462                 if (m_useTestAttachment && m_testMode == MODE_STENCIL)
463                         commandClearStencilAttachment(vk, *cmdBuffer, makeOffset2D(0, 0), makeExtent2D(renderSize.x()/2, renderSize.y()), 1u);
464
465                 vk.cmdDraw(*cmdBuffer, numVertices, 1u, 0u, 0u);
466                 endRenderPass(vk, *cmdBuffer);
467
468                 copyImageToBuffer(vk, *cmdBuffer, *colorImage, *colorBuffer, renderSize, VK_ACCESS_SHADER_WRITE_BIT);
469
470                 endCommandBuffer(vk, *cmdBuffer);
471                 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
472         }
473
474         // Log result image
475         {
476                 invalidateAlloc(vk, device, *colorBufferAlloc);
477
478                 const tcu::ConstPixelBufferAccess imagePixelAccess(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1, colorBufferAlloc->getHostPtr());
479
480                 tcu::TestLog& log = m_context.getTestContext().getLog();
481                 log << tcu::TestLog::Image("color0", "Rendered image", imagePixelAccess);
482         }
483
484         // Verify results
485         {
486                 invalidateAlloc(vk, device, *resultBufferAlloc);
487
488                 const int  actualCounter           = *static_cast<deInt32*>(resultBufferAlloc->getHostPtr());
489                 const bool expectPartialResult = (m_useEarlyTests && m_useTestAttachment);
490                 const int  expectedCounter         = expectPartialResult ? renderSize.x() * renderSize.y() / 2 : renderSize.x() * renderSize.y();
491                 const int  tolerance               = expectPartialResult ? de::max(renderSize.x(), renderSize.y()) * 3  : 0;
492                 const int  expectedMin         = de::max(0, expectedCounter - tolerance);
493                 const int  expectedMax             = expectedCounter + tolerance;
494
495                 tcu::TestLog& log = m_context.getTestContext().getLog();
496                 log << tcu::TestLog::Message << "Expected value"
497                         << (expectPartialResult ? " in range: [" + de::toString(expectedMin) + ", " + de::toString(expectedMax) + "]" : ": " + de::toString(expectedCounter))
498                         << tcu::TestLog::EndMessage;
499                 log << tcu::TestLog::Message << "Result value: " << de::toString(actualCounter) << tcu::TestLog::EndMessage;
500
501                 if (expectedMin <= actualCounter && actualCounter <= expectedMax)
502                         return tcu::TestStatus::pass("Success");
503                 else
504                         return tcu::TestStatus::fail("Value out of range");
505         }
506 }
507
508 TestInstance* EarlyFragmentTest::createInstance (Context& context) const
509 {
510         return new EarlyFragmentTestInstance(context, m_flags);
511 }
512
513 void EarlyFragmentTest::checkSupport (Context& context) const
514 {
515         context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_FRAGMENT_STORES_AND_ATOMICS);
516 }
517
518 class EarlyFragmentDiscardTestInstance : public EarlyFragmentTestInstance
519 {
520 public:
521                                                         EarlyFragmentDiscardTestInstance        (Context& context, const deUint32 flags);
522
523         tcu::TestStatus                 iterate                                                         (void);
524
525 private:
526         tcu::TextureLevel       generateReferenceColorImage                             (const tcu::TextureFormat format, const tcu::IVec2& renderSize);
527         enum TestMode
528         {
529                 MODE_INVALID,
530                 MODE_DEPTH,
531                 MODE_STENCIL,
532         };
533
534         const TestMode                  m_testMode;
535         const bool                              m_useTestAttachment;
536         const bool                              m_useEarlyTests;
537 };
538
539 EarlyFragmentDiscardTestInstance::EarlyFragmentDiscardTestInstance (Context& context, const deUint32 flags)
540         : EarlyFragmentTestInstance                     (context, flags)
541         , m_testMode                    (flags & FLAG_TEST_DEPTH   ? MODE_DEPTH :
542                                                          flags & FLAG_TEST_STENCIL ? MODE_STENCIL : MODE_INVALID)
543         , m_useTestAttachment   ((flags & FLAG_DONT_USE_TEST_ATTACHMENT) == 0)
544         , m_useEarlyTests               ((flags & FLAG_DONT_USE_EARLY_FRAGMENT_TESTS) == 0)
545 {
546         DE_ASSERT(m_testMode != MODE_INVALID);
547 }
548
549 tcu::TextureLevel EarlyFragmentDiscardTestInstance::generateReferenceColorImage(const tcu::TextureFormat format, const tcu::IVec2 &renderSize)
550 {
551         tcu::TextureLevel       image(format, renderSize.x(), renderSize.y());
552         const tcu::Vec4         clearColor      = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
553
554         tcu::clear(image.getAccess(), clearColor);
555
556         return image;
557 }
558
559 tcu::TestStatus EarlyFragmentDiscardTestInstance::iterate (void)
560 {
561         const DeviceInterface&          vk                                      = m_context.getDeviceInterface();
562         const InstanceInterface&        vki                                     = m_context.getInstanceInterface();
563         const VkDevice                          device                          = m_context.getDevice();
564         const VkPhysicalDevice          physDevice                      = m_context.getPhysicalDevice();
565         const VkQueue                           queue                           = m_context.getUniversalQueue();
566         const deUint32                          queueFamilyIndex        = m_context.getUniversalQueueFamilyIndex();
567         Allocator&                                      allocator                       = m_context.getDefaultAllocator();
568
569         DE_ASSERT(m_useTestAttachment);
570
571         // Color attachment
572         const tcu::IVec2                                renderSize                              = tcu::IVec2(32, 32);
573         const VkFormat                                  colorFormat                             = VK_FORMAT_R8G8B8A8_UNORM;
574         const VkImageSubresourceRange   colorSubresourceRange   = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
575         const Unique<VkImage>                   colorImage                              (makeImage(vk, device, makeImageCreateInfo(renderSize, colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
576         const UniquePtr<Allocation>             colorImageAlloc                 (bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any));
577         const Unique<VkImageView>               colorImageView                  (makeImageView(vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange));
578
579         // Test attachment (depth or stencil)
580         static const VkFormat stencilFormats[] =
581         {
582                 // One of the following formats must be supported, as per spec requirement.
583                 VK_FORMAT_S8_UINT,
584                 VK_FORMAT_D16_UNORM_S8_UINT,
585                 VK_FORMAT_D24_UNORM_S8_UINT,
586                 VK_FORMAT_D32_SFLOAT_S8_UINT,
587         };
588
589         const VkFormat depthStencilFormat = (m_testMode == MODE_STENCIL ? pickSupportedDepthStencilFormat(vki, physDevice, DE_LENGTH_OF_ARRAY(stencilFormats), stencilFormats)
590                                                                                  : VK_FORMAT_D16_UNORM);                // spec requires this format to be supported
591
592         if (depthStencilFormat == VK_FORMAT_UNDEFINED)
593                 return tcu::TestStatus::fail("Required depth/stencil format not supported");
594
595         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Using depth/stencil format " << getFormatName(depthStencilFormat) << tcu::TestLog::EndMessage;
596
597         const VkImageSubresourceRange   testSubresourceRange    = makeImageSubresourceRange(getImageAspectFlags(depthStencilFormat), 0u, 1u, 0u, 1u);
598         const Unique<VkImage>                   testImage                               (makeImage(vk, device, makeImageCreateInfo(renderSize, depthStencilFormat, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
599         const UniquePtr<Allocation>             testImageAlloc                  (bindImage(vk, device, allocator, *testImage, MemoryRequirement::Any));
600         const Unique<VkImageView>               testImageView                   (makeImageView(vk, device, *testImage, VK_IMAGE_VIEW_TYPE_2D, depthStencilFormat, testSubresourceRange));
601         const VkImageView                               attachmentImages[]              = { *colorImageView, *testImageView };
602         const deUint32                                  numUsedAttachmentImages = DE_LENGTH_OF_ARRAY(attachmentImages);
603
604         // Vertex buffer
605
606         const deUint32                                  numVertices                             = 6;
607         const VkDeviceSize                              vertexBufferSizeBytes   = sizeof(tcu::Vec4) * numVertices;
608         const Unique<VkBuffer>                  vertexBuffer                    (makeBuffer(vk, device, vertexBufferSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
609         const UniquePtr<Allocation>             vertexBufferAlloc               (bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible));
610
611         {
612                 tcu::Vec4* const pVertices = reinterpret_cast<tcu::Vec4*>(vertexBufferAlloc->getHostPtr());
613
614                 pVertices[0] = tcu::Vec4( 1.0f, -1.0f,  0.5f,  1.0f);
615                 pVertices[1] = tcu::Vec4(-1.0f, -1.0f,  0.0f,  1.0f);
616                 pVertices[2] = tcu::Vec4(-1.0f,  1.0f,  0.5f,  1.0f);
617
618                 pVertices[3] = tcu::Vec4(-1.0f,  1.0f,  0.5f,  1.0f);
619                 pVertices[4] = tcu::Vec4( 1.0f,  1.0f,  1.0f,  1.0f);
620                 pVertices[5] = tcu::Vec4( 1.0f, -1.0f,  0.5f,  1.0f);
621
622                 flushAlloc(vk, device, *vertexBufferAlloc);
623                 // No barrier needed, flushed memory is automatically visible
624         }
625
626         // Result buffer
627
628         const VkDeviceSize                              resultBufferSizeBytes   = sizeof(deUint32);
629         const Unique<VkBuffer>                  resultBuffer                    (makeBuffer(vk, device, resultBufferSizeBytes, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT));
630         const UniquePtr<Allocation>             resultBufferAlloc               (bindBuffer(vk, device, allocator, *resultBuffer, MemoryRequirement::HostVisible));
631
632         {
633                 deUint32* const pData = static_cast<deUint32*>(resultBufferAlloc->getHostPtr());
634
635                 *pData = 0;
636                 flushAlloc(vk, device, *resultBufferAlloc);
637         }
638
639         // Render result buffer (to retrieve color attachment contents)
640
641         const VkDeviceSize                              colorBufferSizeBytes    = tcu::getPixelSize(mapVkFormat(colorFormat)) * renderSize.x() * renderSize.y();
642         const Unique<VkBuffer>                  colorBuffer                             (makeBuffer(vk, device, colorBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
643         const UniquePtr<Allocation>             colorBufferAlloc                (bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
644
645         // Depth stencil result buffer (to retrieve depth-stencil attachment contents)
646
647         const VkDeviceSize                              dsBufferSizeBytes       = tcu::getPixelSize(mapVkFormat(depthStencilFormat)) * renderSize.x() * renderSize.y();
648         const Unique<VkBuffer>                  dsBuffer                        (makeBuffer(vk, device, dsBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
649         const UniquePtr<Allocation>             dsBufferAlloc           (bindBuffer(vk, device, allocator, *dsBuffer, MemoryRequirement::HostVisible));
650
651         // Descriptors
652
653         const Unique<VkDescriptorSetLayout> descriptorSetLayout(DescriptorSetLayoutBuilder()
654                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT)
655                 .build(vk, device));
656
657         const Unique<VkDescriptorPool> descriptorPool(DescriptorPoolBuilder()
658                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
659                 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
660
661         const Unique<VkDescriptorSet> descriptorSet                              (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
662         const VkDescriptorBufferInfo  resultBufferDescriptorInfo = makeDescriptorBufferInfo(resultBuffer.get(), 0ull, resultBufferSizeBytes);
663
664         DescriptorSetUpdateBuilder()
665                 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultBufferDescriptorInfo)
666                 .update(vk, device);
667
668         // Pipeline
669
670         const Unique<VkShaderModule>    vertexModule  (createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
671         const Unique<VkShaderModule>    fragmentModule(createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u));
672         const Unique<VkRenderPass>              renderPass        (makeRenderPass(vk, device, colorFormat, m_useTestAttachment, depthStencilFormat));
673         const Unique<VkFramebuffer>             framebuffer       (makeFramebuffer(vk, device, *renderPass, numUsedAttachmentImages, attachmentImages, renderSize.x(), renderSize.y()));
674         const Unique<VkPipelineLayout>  pipelineLayout(makePipelineLayout(vk, device, *descriptorSetLayout));
675         const Unique<VkPipeline>                pipeline          (makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule, renderSize,
676                                                                                                                                                 (m_testMode == MODE_DEPTH), (m_testMode == MODE_STENCIL),
677                                                                                                                                                 VK_STENCIL_OP_INCREMENT_AND_CLAMP, VK_STENCIL_OP_INCREMENT_AND_CLAMP));
678         const Unique<VkCommandPool>             cmdPool           (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
679         const Unique<VkCommandBuffer>   cmdBuffer         (allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
680
681         // Draw commands
682         {
683                 const VkRect2D renderArea = {
684                         makeOffset2D(0, 0),
685                         makeExtent2D(renderSize.x(), renderSize.y()),
686                 };
687                 const tcu::Vec4 clearColor(0.0f, 0.0f, 0.0f, 1.0f);
688                 const VkDeviceSize vertexBufferOffset = 0ull;
689
690                 beginCommandBuffer(vk, *cmdBuffer);
691
692                 {
693                         const VkImageMemoryBarrier barriers[] = {
694                                 makeImageMemoryBarrier(
695                                         0u, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
696                                         VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
697                                         *colorImage, colorSubresourceRange),
698                                 makeImageMemoryBarrier(
699                                         0u, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
700                                         VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
701                                         *testImage, testSubresourceRange),
702                         };
703
704                         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u,
705                                 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
706                 }
707
708                 // Will clear the attachments with specified depth and stencil values.
709                 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea, clearColor, 0.5f, 3u);
710
711                 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
712                 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
713                 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
714
715                 // Mask half of the attachment image with value that will pass the stencil test.
716                 if (m_testMode == MODE_STENCIL)
717                         commandClearStencilAttachment(vk, *cmdBuffer, makeOffset2D(0, 0), makeExtent2D(renderSize.x()/2, renderSize.y()), 1u);
718
719                 vk.cmdDraw(*cmdBuffer, numVertices, 1u, 0u, 0u);
720                 endRenderPass(vk, *cmdBuffer);
721
722                 copyImageToBuffer(vk, *cmdBuffer, *colorImage, *colorBuffer, renderSize, VK_ACCESS_SHADER_WRITE_BIT);
723                 VkImageAspectFlags dsAspect = m_testMode == MODE_DEPTH ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_STENCIL_BIT;
724                 copyImageToBuffer(vk, *cmdBuffer, *testImage, *dsBuffer, renderSize, VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL, 1u, dsAspect, dsAspect);
725
726                 endCommandBuffer(vk, *cmdBuffer);
727                 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
728         }
729
730         // Verify color output
731         {
732                 invalidateAlloc(vk, device, *colorBufferAlloc);
733
734                 const tcu::ConstPixelBufferAccess       imagePixelAccess(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1, colorBufferAlloc->getHostPtr());
735                 const tcu::TextureLevel                         referenceImage  = generateReferenceColorImage(mapVkFormat(colorFormat), renderSize);
736                 if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", referenceImage.getAccess(), imagePixelAccess, tcu::Vec4(0.02f), tcu::COMPARE_LOG_RESULT))
737                         printf("Rendered color image is not correct");
738         }
739
740         // Verify depth-stencil output
741         {
742                 invalidateAlloc(vk, device, *dsBufferAlloc);
743                 tcu::TextureFormat format = mapVkFormat(depthStencilFormat);
744                 const tcu::ConstPixelBufferAccess       dsPixelAccess (format, renderSize.x(), renderSize.y(), 1, dsBufferAlloc->getHostPtr());
745
746                 for(int z = 0; z < dsPixelAccess.getDepth(); z++)
747                 for(int y = 0; y < dsPixelAccess.getHeight(); y++)
748                 for(int x = 0; x < dsPixelAccess.getWidth(); x++)
749                 {
750                         float   depthValue              = (m_testMode == MODE_DEPTH) ? dsPixelAccess.getPixDepth(x, y, z) : 0.0f;
751                         int             stencilValue    = (m_testMode == MODE_STENCIL) ? dsPixelAccess.getPixStencil(x, y, z) : 0;
752
753                         // Depth test should write to the depth buffer even when there is a discard in the fragment shader,
754                         // when early fragment tests are enabled.
755                         if (m_testMode == MODE_DEPTH)
756                         {
757                                 if (m_useEarlyTests && ((x + y) < 31) && depthValue >= 0.5f)
758                                 {
759                                         std::ostringstream error;
760                                         error << "Rendered depth value [ "<< x << ", " << y << ", " << z << "] is not correct: " << depthValue << " >= 0.5f";
761                                         TCU_FAIL(error.str().c_str());
762                                 }
763                                 // When early fragment tests are disabled, the depth test happens after the fragment shader, but as we are discarding
764                                 // all fragments, the stored value in the depth buffer should be the clear one (0.5f).
765                                 if (!m_useEarlyTests && deAbs(depthValue - 0.5f) > 0.01f)
766                                 {
767                                         std::ostringstream error;
768                                         error << "Rendered depth value [ "<< x << ", " << y << ", " << z << "] is not correct: " << depthValue << " != 0.5f";
769                                         TCU_FAIL(error.str().c_str());
770                                 }
771                         }
772
773                         if (m_testMode == MODE_STENCIL)
774                         {
775                                 if (m_useEarlyTests && ((x < 16 && stencilValue != 2u) || (x >= 16 && stencilValue != 4u)))
776                                 {
777                                         std::ostringstream error;
778                                         error << "Rendered stencil value [ "<< x << ", " << y << ", " << z << "] is not correct: " << stencilValue << " != ";
779                                         error << (x < 16 ? 2u : 4u);
780                                         TCU_FAIL(error.str().c_str());
781                                 }
782
783                                 if (!m_useEarlyTests && ((x < 16 && stencilValue != 1u) || (x >= 16 && stencilValue != 3u)))
784                                 {
785                                         std::ostringstream error;
786                                         error << "Rendered stencil value [ "<< x << ", " << y << ", " << z << "] is not correct: " << stencilValue << " != ";
787                                         error << (x < 16 ? 1u : 3u);
788                                         TCU_FAIL(error.str().c_str());
789                                 }
790                         }
791                 }
792         }
793
794         // Verify we process all the fragments
795         {
796                 invalidateAlloc(vk, device, *resultBufferAlloc);
797
798                 const int  actualCounter           = *static_cast<deInt32*>(resultBufferAlloc->getHostPtr());
799                 const bool expectPartialResult = m_useEarlyTests;
800                 const int  expectedCounter         = expectPartialResult ? renderSize.x() * renderSize.y() / 2 : renderSize.x() * renderSize.y();
801                 const int  tolerance               = expectPartialResult ? de::max(renderSize.x(), renderSize.y()) * 3  : 0;
802                 const int  expectedMin         = de::max(0, expectedCounter - tolerance);
803                 const int  expectedMax             = expectedCounter + tolerance;
804
805                 tcu::TestLog& log = m_context.getTestContext().getLog();
806                 log << tcu::TestLog::Message << "Expected value"
807                         << (expectPartialResult ? " in range: [" + de::toString(expectedMin) + ", " + de::toString(expectedMax) + "]" : ": " + de::toString(expectedCounter))
808                         << tcu::TestLog::EndMessage;
809                 log << tcu::TestLog::Message << "Result value: " << de::toString(actualCounter) << tcu::TestLog::EndMessage;
810
811                 if (expectedMin <= actualCounter && actualCounter <= expectedMax)
812                         return tcu::TestStatus::pass("Success");
813                 else
814                         return tcu::TestStatus::fail("Value out of range");
815         }
816 }
817
818 class EarlyFragmentDiscardTest : public EarlyFragmentTest
819 {
820 public:
821                                                 EarlyFragmentDiscardTest        (tcu::TestContext&              testCtx,
822                                                                                                          const std::string              name,
823                                                                                                          const deUint32                 flags);
824
825         void                            initPrograms                            (SourceCollections&             programCollection) const;
826         TestInstance*           createInstance                          (Context&                               context) const;
827
828 private:
829         const deUint32          m_flags;
830 };
831
832 EarlyFragmentDiscardTest::EarlyFragmentDiscardTest (tcu::TestContext& testCtx, const std::string name, const deUint32 flags)
833         : EarlyFragmentTest     (testCtx, name, flags)
834         , m_flags (flags)
835 {
836 }
837
838 TestInstance* EarlyFragmentDiscardTest::createInstance (Context& context) const
839 {
840         return new EarlyFragmentDiscardTestInstance(context, m_flags);
841 }
842
843 void EarlyFragmentDiscardTest::initPrograms(SourceCollections &programCollection) const
844 {
845         // Vertex
846         {
847                 std::ostringstream src;
848                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
849                         << "\n"
850                         << "layout(location = 0) in highp vec4 position;\n"
851                         << "\n"
852                         << "out gl_PerVertex {\n"
853                         << "   vec4 gl_Position;\n"
854                         << "};\n"
855                         << "\n"
856                         << "void main (void)\n"
857                         << "{\n"
858                         << "    gl_Position = position;\n"
859                         << "}\n";
860
861                 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
862         }
863
864         // Fragment
865         {
866                 const bool useEarlyTests = (m_flags & FLAG_DONT_USE_EARLY_FRAGMENT_TESTS) == 0;
867                 std::ostringstream src;
868                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
869                         << "\n"
870                         << (useEarlyTests ? "layout(early_fragment_tests) in;\n" : "")
871                         << "layout(location = 0) out highp vec4 fragColor;\n"
872                         << "\n"
873                         << "layout(binding = 0) coherent buffer Output {\n"
874                         << "    uint result;\n"
875                         << "} sb_out;\n"
876                         << "\n"
877                         << "void main (void)\n"
878                         << "{\n"
879                         << "    atomicAdd(sb_out.result, 1u);\n"
880                         << "    gl_FragDepth = 0.75f;\n"
881                         << "    fragColor = vec4(1.0, 1.0, 0.0, 1.0);\n"
882                         << "    discard;\n"
883                         << "}\n";
884
885                 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
886         }
887 }
888
889 class EarlyFragmentSampleMaskTestInstance : public EarlyFragmentTestInstance
890 {
891 public:
892                                                         EarlyFragmentSampleMaskTestInstance     (Context& context, const deUint32 flags, const deUint32 sampleCount);
893
894         tcu::TestStatus                 iterate                                                         (void);
895
896 private:
897         tcu::TextureLevel       generateReferenceColorImage                             (const tcu::TextureFormat format, const tcu::IVec2& renderSize);
898         Move<VkRenderPass>  makeRenderPass                                                      (const DeviceInterface&                         vk,
899                                                                                                                                  const VkDevice                                         device,
900                                                                                                                                  const VkFormat                                         colorFormat,
901                                                                                                                                  const VkFormat                                         depthStencilFormat);
902         Move<VkPipeline>        makeGraphicsPipeline                                    (const DeviceInterface& vk,
903                                                                                                                                  const VkDevice                 device,
904                                                                                                                                  const VkPipelineLayout pipelineLayout,
905                                                                                                                                  const VkRenderPass             renderPass,
906                                                                                                                                  const VkShaderModule           vertexModule,
907                                                                                                                                  const VkShaderModule           fragmentModule,
908                                                                                                                                  const tcu::IVec2&              renderSize,
909                                                                                                                                  const bool                             enableDepthTest,
910                                                                                                                                  const bool                             enableStencilTest,
911                                                                                                                                  const VkStencilOp              stencilFailOp,
912                                                                                                                                  const VkStencilOp              stencilPassOp);
913         enum TestMode
914         {
915                 MODE_INVALID,
916                 MODE_DEPTH,
917                 MODE_STENCIL,
918         };
919
920         const TestMode                  m_testMode;
921         const bool                              m_useTestAttachment;
922         const bool                              m_useEarlyTests;
923         const deUint32                  m_sampleCount;
924 };
925
926 EarlyFragmentSampleMaskTestInstance::EarlyFragmentSampleMaskTestInstance (Context& context, const deUint32 flags, const deUint32 sampleCount)
927         : EarlyFragmentTestInstance                     (context, flags)
928         , m_testMode                    (flags & FLAG_TEST_DEPTH   ? MODE_DEPTH :
929                                                          flags & FLAG_TEST_STENCIL ? MODE_STENCIL : MODE_INVALID)
930         , m_useTestAttachment   ((flags & FLAG_DONT_USE_TEST_ATTACHMENT) == 0)
931         , m_useEarlyTests               ((flags & FLAG_DONT_USE_EARLY_FRAGMENT_TESTS) == 0)
932         , m_sampleCount                 (sampleCount)
933 {
934         DE_ASSERT(m_testMode != MODE_INVALID);
935 }
936
937 tcu::TextureLevel EarlyFragmentSampleMaskTestInstance::generateReferenceColorImage(const tcu::TextureFormat format, const tcu::IVec2 &renderSize)
938 {
939         tcu::TextureLevel       image(format, renderSize.x(), renderSize.y());
940         const tcu::Vec4         clearColor      = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
941
942         tcu::clear(image.getAccess(), clearColor);
943
944         return image;
945 }
946
947 Move<VkPipeline> EarlyFragmentSampleMaskTestInstance::makeGraphicsPipeline (const DeviceInterface&      vk,
948                                                                                                                                                         const VkDevice                  device,
949                                                                                                                                                         const VkPipelineLayout  pipelineLayout,
950                                                                                                                                                         const VkRenderPass              renderPass,
951                                                                                                                                                         const VkShaderModule            vertexModule,
952                                                                                                                                                         const VkShaderModule            fragmentModule,
953                                                                                                                                                         const tcu::IVec2&               renderSize,
954                                                                                                                                                         const bool                              enableDepthTest,
955                                                                                                                                                         const bool                              enableStencilTest,
956                                                                                                                                                         const VkStencilOp               stencilFailOp,
957                                                                                                                                                         const VkStencilOp               stencilPassOp)
958 {
959         const std::vector<VkViewport>                   viewports                                       (1, makeViewport(renderSize));
960         const std::vector<VkRect2D>                             scissors                                        (1, makeRect2D(renderSize));
961
962         const VkStencilOpState                                  stencilOpState                          = makeStencilOpState(
963                 stencilFailOp,                  // stencil fail
964                 stencilPassOp,                  // depth & stencil pass
965                 VK_STENCIL_OP_KEEP,             // depth only fail
966                 VK_COMPARE_OP_EQUAL,    // compare op
967                 0x3,                                    // compare mask
968                 0xf,                                    // write mask
969                 1u);                                    // reference
970
971         const VkPipelineDepthStencilStateCreateInfo     depthStencilStateCreateInfo     =
972         {
973                 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,     // VkStructureType                          sType
974                 DE_NULL,                                                                                                        // const void*                              pNext
975                 0u,                                                                                                                     // VkPipelineDepthStencilStateCreateFlags   flags
976                 enableDepthTest ? VK_TRUE : VK_FALSE,                                           // VkBool32                                 depthTestEnable
977                 enableDepthTest ? VK_TRUE : VK_FALSE,                                           // VkBool32                                 depthWriteEnable
978                 VK_COMPARE_OP_LESS,                                                                                     // VkCompareOp                              depthCompareOp
979                 VK_FALSE,                                                                                                       // VkBool32                                 depthBoundsTestEnable
980                 enableStencilTest ? VK_TRUE : VK_FALSE,                                         // VkBool32                                 stencilTestEnable
981                 stencilOpState,                                                                                         // VkStencilOpState                         front
982                 stencilOpState,                                                                                         // VkStencilOpState                         back
983                 0.0f,                                                                                                           // float                                    minDepthBounds
984                 1.0f                                                                                                            // float                                    maxDepthBounds
985         };
986
987         // Only allow coverage on sample 0.
988         const VkSampleMask sampleMask = 0x1;
989
990         const VkPipelineMultisampleStateCreateInfo multisampleStateCreateInfo =
991         {
992                 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,       // VkStructureType                                                      sType
993                 DE_NULL,                                                                                                        // const void*                                                          pNext
994                 0u,                                                                                                                     // VkPipelineMultisampleStateCreateFlags        flags
995                 (VkSampleCountFlagBits)m_sampleCount,                                           // VkSampleCountFlagBits                                        rasterizationSamples
996                 DE_TRUE,                                                                                                        // VkBool32                                                                     sampleShadingEnable
997                 0.0f,                                                                                                           // float                                                                        minSampleShading
998                 &sampleMask,                                                                                            // const VkSampleMask*                                          pSampleMask
999                 DE_FALSE,                                                                                                       // VkBool32                                                                     alphaToCoverageEnable
1000                 DE_FALSE,                                                                                                       // VkBool32                                                                     alphaToOneEnable
1001         };
1002
1003         return vk::makeGraphicsPipeline(vk,                                                                             // const DeviceInterface&                        vk
1004                                                                         device,                                                                 // const VkDevice                                device
1005                                                                         pipelineLayout,                                                 // const VkPipelineLayout                        pipelineLayout
1006                                                                         vertexModule,                                                   // const VkShaderModule                          vertexShaderModule
1007                                                                         DE_NULL,                                                                // const VkShaderModule                          tessellationControlModule
1008                                                                         DE_NULL,                                                                // const VkShaderModule                          tessellationEvalModule
1009                                                                         DE_NULL,                                                                // const VkShaderModule                          geometryShaderModule
1010                                                                         fragmentModule,                                                 // const VkShaderModule                          fragmentShaderModule
1011                                                                         renderPass,                                                             // const VkRenderPass                            renderPass
1012                                                                         viewports,                                                              // const std::vector<VkViewport>&                viewports
1013                                                                         scissors,                                                               // const std::vector<VkRect2D>&                  scissors
1014                                                                         VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,    // const VkPrimitiveTopology                     topology
1015                                                                         0u,                                                                             // const deUint32                                subpass
1016                                                                         0u,                                                                             // const deUint32                                patchControlPoints
1017                                                                         DE_NULL,                                                                // const VkPipelineVertexInputStateCreateInfo*   vertexInputStateCreateInfo
1018                                                                         DE_NULL,                                                                // const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
1019                                                                         &multisampleStateCreateInfo,                    // const VkPipelineMultisampleStateCreateInfo*   multisampleStateCreateInfo
1020                                                                         &depthStencilStateCreateInfo);                  // const VkPipelineDepthStencilStateCreateInfo*  depthStencilStateCreateInfo
1021 }
1022
1023 Move<VkRenderPass> EarlyFragmentSampleMaskTestInstance::makeRenderPass (const DeviceInterface&                          vk,
1024                                                                                                                                                 const VkDevice                                          device,
1025                                                                                                                                                 const VkFormat                                          colorFormat,
1026                                                                                                                                                 const VkFormat                                          depthStencilFormat)
1027 {
1028         const bool                                                              hasColor                                                        = colorFormat != VK_FORMAT_UNDEFINED;
1029         const bool                                                              hasDepthStencil                                         = depthStencilFormat != VK_FORMAT_UNDEFINED;
1030
1031
1032         const VkAttachmentDescription2                  colorAttachmentDescription                      =
1033         {
1034                 VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2,     // VkStructureType                                      sType;
1035                 DE_NULL,                                                                        // const void*                                          pNext;
1036                 (VkAttachmentDescriptionFlags)0,                        // VkAttachmentDescriptionFlags    flags
1037                 colorFormat,                                                            // VkFormat                        format
1038                 (VkSampleCountFlagBits)m_sampleCount,           // VkSampleCountFlagBits           samples
1039                 VK_ATTACHMENT_LOAD_OP_CLEAR,                            // VkAttachmentLoadOp              loadOp
1040                 VK_ATTACHMENT_STORE_OP_STORE,                           // VkAttachmentStoreOp             storeOp
1041                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,                        // VkAttachmentLoadOp              stencilLoadOp
1042                 VK_ATTACHMENT_STORE_OP_DONT_CARE,                       // VkAttachmentStoreOp             stencilStoreOp
1043                 VK_IMAGE_LAYOUT_UNDEFINED,                                      // VkImageLayout                   initialLayout
1044                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL        // VkImageLayout                   finalLayout
1045         };
1046
1047         const VkAttachmentDescription2                  depthStencilAttachmentDescription       =
1048         {
1049                 VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2,                     // VkStructureType                                      sType;
1050                 DE_NULL,                                                                                        // const void*                                          pNext;
1051                 (VkAttachmentDescriptionFlags)0,                                        // VkAttachmentDescriptionFlags    flags
1052                 depthStencilFormat,                                                                     // VkFormat                        format
1053                 (VkSampleCountFlagBits)m_sampleCount,                           // VkSampleCountFlagBits           samples
1054                 VK_ATTACHMENT_LOAD_OP_CLEAR,                                            // VkAttachmentLoadOp              loadOp
1055                 VK_ATTACHMENT_STORE_OP_STORE,                                           // VkAttachmentStoreOp             storeOp
1056                 VK_ATTACHMENT_LOAD_OP_CLEAR,                                            // VkAttachmentLoadOp              stencilLoadOp
1057                 VK_ATTACHMENT_STORE_OP_STORE,                                           // VkAttachmentStoreOp             stencilStoreOp
1058                 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,       // VkImageLayout                   initialLayout
1059                 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL        // VkImageLayout                   finalLayout
1060         };
1061
1062         const VkAttachmentDescription2                  resolveAttachmentDescription                    =
1063         {
1064                 VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2,     // VkStructureType                                      sType;
1065                 DE_NULL,                                                                        // const void*                                          pNext;
1066                 (VkAttachmentDescriptionFlags)0,                        // VkAttachmentDescriptionFlags    flags
1067                 colorFormat,                                                            // VkFormat                        format
1068                 VK_SAMPLE_COUNT_1_BIT,                                          // VkSampleCountFlagBits           samples
1069                 VK_ATTACHMENT_LOAD_OP_CLEAR,                            // VkAttachmentLoadOp              loadOp
1070                 VK_ATTACHMENT_STORE_OP_STORE,                           // VkAttachmentStoreOp             storeOp
1071                 VK_ATTACHMENT_LOAD_OP_DONT_CARE,                        // VkAttachmentLoadOp              stencilLoadOp
1072                 VK_ATTACHMENT_STORE_OP_DONT_CARE,                       // VkAttachmentStoreOp             stencilStoreOp
1073                 VK_IMAGE_LAYOUT_UNDEFINED,                                      // VkImageLayout                   initialLayout
1074                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL        // VkImageLayout                   finalLayout
1075         };
1076
1077                 const VkAttachmentDescription2          resolveDepthStencilAttachmentDescription        =
1078         {
1079                 VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2,                     // VkStructureType                                      sType;
1080                 DE_NULL,                                                                                        // const void*                                          pNext;
1081                 (VkAttachmentDescriptionFlags)0,                                        // VkAttachmentDescriptionFlags    flags
1082                 depthStencilFormat,                                                                     // VkFormat                        format
1083                 VK_SAMPLE_COUNT_1_BIT,                                                          // VkSampleCountFlagBits           samples
1084                 VK_ATTACHMENT_LOAD_OP_CLEAR,                                            // VkAttachmentLoadOp              loadOp
1085                 VK_ATTACHMENT_STORE_OP_STORE,                                           // VkAttachmentStoreOp             storeOp
1086                 VK_ATTACHMENT_LOAD_OP_CLEAR,                                            // VkAttachmentLoadOp              stencilLoadOp
1087                 VK_ATTACHMENT_STORE_OP_STORE,                                           // VkAttachmentStoreOp             stencilStoreOp
1088                 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,       // VkImageLayout                   initialLayout
1089                 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL        // VkImageLayout                   finalLayout
1090         };
1091
1092         std::vector<VkAttachmentDescription2>   attachmentDescriptions;
1093
1094         if (hasColor)
1095                 attachmentDescriptions.push_back(colorAttachmentDescription);
1096         if (hasDepthStencil)
1097                 attachmentDescriptions.push_back(depthStencilAttachmentDescription);
1098         if (hasColor)
1099                 attachmentDescriptions.push_back(resolveAttachmentDescription);
1100         if (hasDepthStencil)
1101                 attachmentDescriptions.push_back(resolveDepthStencilAttachmentDescription);
1102
1103         const VkAttachmentReference2                            colorAttachmentRef                                      =
1104         {
1105                 VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2,                       // VkStructureType              sType;
1106                 DE_NULL,                                                                                        // const void*                  pNext;
1107                 0u,                                                                                                     // deUint32         attachment
1108                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                       // VkImageLayout    layout
1109                 VK_IMAGE_ASPECT_COLOR_BIT                                                       // VkImageAspectFlags   aspectMask;
1110         };
1111
1112         const VkAttachmentReference2                            depthStencilAttachmentRef                       =
1113         {
1114                 VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2,                                                                                               // VkStructureType              sType;
1115                 DE_NULL,                                                                                                                                                                // const void*                  pNext;
1116             hasDepthStencil ? 1u : 0u,                                                                                                                          // deUint32         attachment
1117                 VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL,                                                                                                // VkImageLayout    layout
1118             m_testMode == MODE_DEPTH ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_STENCIL_BIT          // VkImageAspectFlags   aspectMask;
1119         };
1120
1121         const VkAttachmentReference2                            resolveAttachmentRef                                    =
1122         {
1123                 VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2,                       // VkStructureType              sType;
1124                 DE_NULL,                                                                                        // const void*                  pNext;
1125                 hasColor ? 2u : 0u,                                                                     // deUint32         attachment
1126                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                       // VkImageLayout    layout
1127                 VK_IMAGE_ASPECT_COLOR_BIT                                                       // VkImageAspectFlags   aspectMask;
1128         };
1129
1130         const VkAttachmentReference2                            depthStencilResolveAttachmentRef                        =
1131         {
1132                 VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2,                                                                                               // VkStructureType              sType;
1133                 DE_NULL,                                                                                                                                                                // const void*                  pNext;
1134             hasDepthStencil ? 3u : 0u,                                                                                                                          // deUint32         attachment
1135                 VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL,                                                                                                // VkImageLayout    layout
1136             m_testMode == MODE_DEPTH ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_STENCIL_BIT          // VkImageAspectFlags   aspectMask;
1137         };
1138
1139         // Using VK_RESOLVE_MODE_SAMPLE_ZERO_BIT as resolve mode, so no need to check its support as it is mandatory in the extension.
1140         const VkSubpassDescriptionDepthStencilResolve depthStencilResolveDescription =
1141         {
1142                 VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE,    // VkStructureType                                      sType;
1143                 DE_NULL,                                                                                                                // const void*                                          pNext;
1144                 VK_RESOLVE_MODE_SAMPLE_ZERO_BIT,                                                                // VkResolveModeFlagBits                        depthResolveMode;
1145                 VK_RESOLVE_MODE_SAMPLE_ZERO_BIT,                                                                // VkResolveModeFlagBits                        stencilResolveMode;
1146                 &depthStencilResolveAttachmentRef                                                               // const VkAttachmentReference2*        pDepthStencilResolveAttachment;
1147         };
1148
1149         const VkSubpassDescription2                             subpassDescription                                      =
1150         {
1151                 VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2,                                                // VkStructureType                                      sType;
1152                 hasDepthStencil ? &depthStencilResolveDescription : DE_NULL,    // const void*                                          pNext;
1153                 (VkSubpassDescriptionFlags)0,                                                                   // VkSubpassDescriptionFlags            flags
1154                 VK_PIPELINE_BIND_POINT_GRAPHICS,                                                                // VkPipelineBindPoint                          pipelineBindPoint
1155                 0u,                                                                                                                             // deUint32                                                     viewMask;
1156                 0u,                                                                                                                             // deUint32                                                     inputAttachmentCount
1157                 DE_NULL,                                                                                                                // const VkAttachmentReference2*        pInputAttachments
1158                 hasColor ? 1u : 0u,                                                                                             // deUint32                                                     colorAttachmentCount
1159                 hasColor ? &colorAttachmentRef : DE_NULL,                                               // const VkAttachmentReference2*        pColorAttachments
1160                 hasColor ? &resolveAttachmentRef : DE_NULL,                                             // const VkAttachmentReference2*        pResolveAttachments
1161                 hasDepthStencil ? &depthStencilAttachmentRef : DE_NULL,                 // const VkAttachmentReference2*        pDepthStencilAttachment
1162                 0u,                                                                                                                             // deUint32                                                     preserveAttachmentCount
1163                 DE_NULL                                                                                                                 // const deUint32*                                      pPreserveAttachments
1164         };
1165
1166         const VkRenderPassCreateInfo2                   renderPassInfo                                          =
1167         {
1168                 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2,                                                            // VkStructureType                   sType
1169                 DE_NULL,                                                                                                                                        // const void*                       pNext
1170                 (VkRenderPassCreateFlags)0,                                                                                                     // VkRenderPassCreateFlags           flags
1171                 (deUint32)attachmentDescriptions.size(),                                                                        // deUint32                          attachmentCount
1172                 attachmentDescriptions.size() > 0 ? &attachmentDescriptions[0] : DE_NULL,       // const VkAttachmentDescription2*    pAttachments
1173                 1u,                                                                                                                                                     // deUint32                          subpassCount
1174                 &subpassDescription,                                                                                                            // const VkSubpassDescription2*       pSubpasses
1175                 0u,                                                                                                                                                     // deUint32                          dependencyCount
1176                 DE_NULL,                                                                                                                                        // const VkSubpassDependency*        pDependencies
1177                 0u,                                                                                                                                                     // deUint32                                             correlatedViewMaskCount;
1178                 DE_NULL,                                                                                                                                        // const deUint32*                                      pCorrelatedViewMasks;
1179         };
1180
1181         return createRenderPass2(vk, device, &renderPassInfo, DE_NULL);
1182 }
1183
1184 tcu::TestStatus EarlyFragmentSampleMaskTestInstance::iterate (void)
1185 {
1186         const DeviceInterface&          vk                                      = m_context.getDeviceInterface();
1187         const InstanceInterface&        vki                                     = m_context.getInstanceInterface();
1188         const VkDevice                          device                          = m_context.getDevice();
1189         const VkPhysicalDevice          physDevice                      = m_context.getPhysicalDevice();
1190         const VkQueue                           queue                           = m_context.getUniversalQueue();
1191         const deUint32                          queueFamilyIndex        = m_context.getUniversalQueueFamilyIndex();
1192         Allocator&                                      allocator                       = m_context.getDefaultAllocator();
1193         const VkFormat                          colorFormat                     = VK_FORMAT_R8G8B8A8_UNORM;
1194
1195         DE_ASSERT(m_useTestAttachment);
1196         DE_UNREF(m_useTestAttachment);
1197
1198         // Test attachment (depth or stencil)
1199         static const VkFormat stencilFormats[] =
1200         {
1201                 // One of the following formats must be supported, as per spec requirement.
1202                 VK_FORMAT_S8_UINT,
1203                 VK_FORMAT_D16_UNORM_S8_UINT,
1204                 VK_FORMAT_D24_UNORM_S8_UINT,
1205                 VK_FORMAT_D32_SFLOAT_S8_UINT,
1206         };
1207
1208         const VkFormat depthStencilFormat = (m_testMode == MODE_STENCIL ? pickSupportedDepthStencilFormat(vki, physDevice, DE_LENGTH_OF_ARRAY(stencilFormats), stencilFormats)
1209                                                                                  : VK_FORMAT_D16_UNORM);                // spec requires this format to be supported
1210
1211         if (depthStencilFormat == VK_FORMAT_UNDEFINED)
1212                 return tcu::TestStatus::fail("Required depth/stencil format not supported");
1213
1214         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Using depth/stencil format " << getFormatName(depthStencilFormat) << tcu::TestLog::EndMessage;
1215
1216         // Check support for MSAA image formats used in the test.
1217         VkImageFormatProperties formatProperties;
1218         vki.getPhysicalDeviceImageFormatProperties(physDevice, colorFormat, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 0u, &formatProperties);
1219         if ((formatProperties.sampleCounts & m_sampleCount) == 0)
1220                 TCU_THROW(NotSupportedError, "Format does not support this number of samples for color format");
1221
1222         vki.getPhysicalDeviceImageFormatProperties(physDevice, depthStencilFormat, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 0u, &formatProperties);
1223         if ((formatProperties.sampleCounts & m_sampleCount) == 0)
1224                 TCU_THROW(NotSupportedError, "Format does not support this number of samples for depth-stencil format");
1225
1226         // Color attachment
1227         const tcu::IVec2                                renderSize                              = tcu::IVec2(32, 32);
1228         const VkImageSubresourceRange   colorSubresourceRange   = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
1229
1230         const VkImageCreateInfo imageParams =
1231         {
1232                 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                                                                            // VkStructureType                      sType;
1233                 DE_NULL,                                                                                                                                        // const void*                          pNext;
1234                 (VkImageCreateFlags)0,                                                                                                          // VkImageCreateFlags           flags;
1235                 VK_IMAGE_TYPE_2D,                                                                                                                       // VkImageType                          imageType;
1236                 colorFormat,                                                                                                                            // VkFormat                                     format;
1237                 makeExtent3D(renderSize.x(), renderSize.y(), 1),                                                        // VkExtent3D                           extent;
1238                 1u,                                                                                                                                                     // deUint32                                     mipLevels;
1239                 1u,                                                                                                                                                     // deUint32                                     arrayLayers;
1240                 (VkSampleCountFlagBits)m_sampleCount,                                                                           // VkSampleCountFlagBits        samples;
1241                 VK_IMAGE_TILING_OPTIMAL,                                                                                                        // VkImageTiling                        tiling;
1242                 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,          // VkImageUsageFlags            usage;
1243                 VK_SHARING_MODE_EXCLUSIVE,                                                                                                      // VkSharingMode                        sharingMode;
1244                 0u,                                                                                                                                                     // deUint32                                     queueFamilyIndexCount;
1245                 DE_NULL,                                                                                                                                        // const deUint32*                      pQueueFamilyIndices;
1246                 VK_IMAGE_LAYOUT_UNDEFINED,                                                                                                      // VkImageLayout                        initialLayout;
1247         };
1248         const Unique<VkImage>                   colorImage                              (makeImage(vk, device, imageParams));
1249         const UniquePtr<Allocation>             colorImageAlloc                 (bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any));
1250         const Unique<VkImageView>               colorImageView                  (makeImageView(vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange));
1251
1252         const Unique<VkImage>                   resolveColorImage               (makeImage(vk, device, makeImageCreateInfo(renderSize, colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
1253         const UniquePtr<Allocation>             resolveColorImageAlloc  (bindImage(vk, device, allocator, *resolveColorImage, MemoryRequirement::Any));
1254         const Unique<VkImageView>               resolveColorImageView   (makeImageView(vk, device, *resolveColorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange));
1255
1256         // Depth-Stencil attachment
1257         const VkImageSubresourceRange   depthStencilSubresourceRange    = makeImageSubresourceRange(getImageAspectFlags(depthStencilFormat), 0u, 1u, 0u, 1u);
1258
1259         const VkImageCreateInfo depthStencilImageParams =
1260         {
1261                 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                                                                                            // VkStructureType                      sType;
1262                 DE_NULL,                                                                                                                                                        // const void*                          pNext;
1263                 (VkImageCreateFlags)0,                                                                                                                          // VkImageCreateFlags           flags;
1264                 VK_IMAGE_TYPE_2D,                                                                                                                                       // VkImageType                          imageType;
1265                 depthStencilFormat,                                                                                                                                                     // VkFormat                                     format;
1266                 makeExtent3D(renderSize.x(), renderSize.y(), 1),                                                                        // VkExtent3D                           extent;
1267                 1u,                                                                                                                                                                     // deUint32                                     mipLevels;
1268                 1u,                                                                                                                                                                     // deUint32                                     arrayLayers;
1269                 (VkSampleCountFlagBits)m_sampleCount,                                                                                           // VkSampleCountFlagBits        samples;
1270                 VK_IMAGE_TILING_OPTIMAL,                                                                                                                        // VkImageTiling                        tiling;
1271                 VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,          // VkImageUsageFlags            usage;
1272                 VK_SHARING_MODE_EXCLUSIVE,                                                                                                                      // VkSharingMode                        sharingMode;
1273                 0u,                                                                                                                                                                     // deUint32                                     queueFamilyIndexCount;
1274                 DE_NULL,                                                                                                                                                        // const deUint32*                      pQueueFamilyIndices;
1275                 VK_IMAGE_LAYOUT_UNDEFINED,                                                                                                                      // VkImageLayout                        initialLayout;
1276         };
1277         const Unique<VkImage>                   depthStencilImage                               (makeImage(vk, device, depthStencilImageParams));
1278         const UniquePtr<Allocation>             depthStencilImageAlloc                  (bindImage(vk, device, allocator, *depthStencilImage, MemoryRequirement::Any));
1279         const Unique<VkImageView>               depthStencilImageView                   (makeImageView(vk, device, *depthStencilImage, VK_IMAGE_VIEW_TYPE_2D, depthStencilFormat, depthStencilSubresourceRange));
1280
1281         const Unique<VkImage>                   resolveDepthStencilImage                                (makeImage(vk, device, makeImageCreateInfo(renderSize, depthStencilFormat, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
1282         const UniquePtr<Allocation>             resolveDepthStencilImageAlloc                   (bindImage(vk, device, allocator, *resolveDepthStencilImage, MemoryRequirement::Any));
1283         const Unique<VkImageView>               resolveDepthStencilImageView                    (makeImageView(vk, device, *resolveDepthStencilImage, VK_IMAGE_VIEW_TYPE_2D, depthStencilFormat, depthStencilSubresourceRange));
1284
1285         const VkImageView                               attachmentImages[]              = { *colorImageView, *depthStencilImageView, *resolveColorImageView, *resolveDepthStencilImageView };
1286         const deUint32                                  numUsedAttachmentImages = DE_LENGTH_OF_ARRAY(attachmentImages);
1287
1288         // Vertex buffer
1289
1290         const deUint32                                  numVertices                             = 6u;
1291         const VkDeviceSize                              vertexBufferSizeBytes   = sizeof(tcu::Vec4) * numVertices;
1292         const Unique<VkBuffer>                  vertexBuffer                    (makeBuffer(vk, device, vertexBufferSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
1293         const UniquePtr<Allocation>             vertexBufferAlloc               (bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible));
1294
1295         {
1296                 tcu::Vec4* const pVertices = reinterpret_cast<tcu::Vec4*>(vertexBufferAlloc->getHostPtr());
1297
1298                 pVertices[0] = tcu::Vec4( 1.0f, -1.0f,  0.5f,  1.0f);
1299                 pVertices[1] = tcu::Vec4(-1.0f, -1.0f,  0.0f,  1.0f);
1300                 pVertices[2] = tcu::Vec4(-1.0f,  1.0f,  0.5f,  1.0f);
1301
1302                 pVertices[3] = tcu::Vec4(-1.0f,  1.0f,  0.5f,  1.0f);
1303                 pVertices[4] = tcu::Vec4( 1.0f,  1.0f,  1.0f,  1.0f);
1304                 pVertices[5] = tcu::Vec4( 1.0f, -1.0f,  0.5f,  1.0f);
1305
1306                 flushAlloc(vk, device, *vertexBufferAlloc);
1307                 // No barrier needed, flushed memory is automatically visible
1308         }
1309
1310         // Result buffer
1311
1312         const VkDeviceSize                              resultBufferSizeBytes   = sizeof(deUint32);
1313         const Unique<VkBuffer>                  resultBuffer                    (makeBuffer(vk, device, resultBufferSizeBytes, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT));
1314         const UniquePtr<Allocation>             resultBufferAlloc               (bindBuffer(vk, device, allocator, *resultBuffer, MemoryRequirement::HostVisible));
1315
1316         {
1317                 deUint32* const pData = static_cast<deUint32*>(resultBufferAlloc->getHostPtr());
1318
1319                 *pData = 0;
1320                 flushAlloc(vk, device, *resultBufferAlloc);
1321         }
1322
1323         // Render result buffer (to retrieve color attachment contents)
1324
1325         const VkDeviceSize                              colorBufferSizeBytes    = tcu::getPixelSize(mapVkFormat(colorFormat)) * renderSize.x() * renderSize.y();
1326         const Unique<VkBuffer>                  colorBuffer                             (makeBuffer(vk, device, colorBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1327         const UniquePtr<Allocation>             colorBufferAlloc                (bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
1328
1329         // Depth stencil result buffer (to retrieve depth-stencil attachment contents)
1330
1331         const VkDeviceSize                              dsBufferSizeBytes       = tcu::getPixelSize(mapVkFormat(depthStencilFormat)) * renderSize.x() * renderSize.y();
1332         const Unique<VkBuffer>                  dsBuffer                        (makeBuffer(vk, device, dsBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1333         const UniquePtr<Allocation>             dsBufferAlloc           (bindBuffer(vk, device, allocator, *dsBuffer, MemoryRequirement::HostVisible));
1334
1335         // Descriptors
1336
1337         const Unique<VkDescriptorSetLayout> descriptorSetLayout(DescriptorSetLayoutBuilder()
1338                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT)
1339                 .build(vk, device));
1340
1341         const Unique<VkDescriptorPool> descriptorPool(DescriptorPoolBuilder()
1342                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
1343                 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
1344
1345         const Unique<VkDescriptorSet> descriptorSet                              (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
1346         const VkDescriptorBufferInfo  resultBufferDescriptorInfo = makeDescriptorBufferInfo(resultBuffer.get(), 0ull, resultBufferSizeBytes);
1347
1348         DescriptorSetUpdateBuilder()
1349                 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultBufferDescriptorInfo)
1350                 .update(vk, device);
1351
1352         // Pipeline
1353
1354         const Unique<VkShaderModule>    vertexModule  (createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
1355         const Unique<VkShaderModule>    fragmentModule(createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u));
1356
1357         const Unique<VkRenderPass>              renderPass        (makeRenderPass(vk, device, colorFormat, depthStencilFormat));
1358         const Unique<VkFramebuffer>             framebuffer       (makeFramebuffer(vk, device, *renderPass, numUsedAttachmentImages, attachmentImages, renderSize.x(), renderSize.y()));
1359         const Unique<VkPipelineLayout>  pipelineLayout(makePipelineLayout(vk, device, *descriptorSetLayout));
1360         const Unique<VkPipeline>                pipeline          (makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule, renderSize,
1361                                                                                                                                                 (m_testMode == MODE_DEPTH), (m_testMode == MODE_STENCIL),
1362                                                                                                                                                 VK_STENCIL_OP_INCREMENT_AND_CLAMP, VK_STENCIL_OP_INCREMENT_AND_CLAMP));
1363         const Unique<VkCommandPool>             cmdPool           (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1364         const Unique<VkCommandBuffer>   cmdBuffer         (allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1365
1366         // Draw commands
1367
1368         {
1369                 const VkRect2D renderArea = {
1370                         makeOffset2D(0, 0),
1371                         makeExtent2D(renderSize.x(), renderSize.y()),
1372                 };
1373                 const tcu::Vec4 clearColor(0.0f, 0.0f, 0.0f, 1.0f);
1374                 const VkDeviceSize vertexBufferOffset = 0ull;
1375
1376                 beginCommandBuffer(vk, *cmdBuffer);
1377
1378                 {
1379                         const VkImageMemoryBarrier barriers[] = {
1380                                 makeImageMemoryBarrier(
1381                                         0u, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
1382                                         VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
1383                                         *colorImage, colorSubresourceRange),
1384                                 makeImageMemoryBarrier(
1385                                         0u, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
1386                                         VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
1387                                         *depthStencilImage, depthStencilSubresourceRange),
1388                                 makeImageMemoryBarrier(
1389                                         0u,  VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
1390                                         VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
1391                                         *resolveColorImage, colorSubresourceRange),
1392                                 makeImageMemoryBarrier(
1393                                         0u, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
1394                                         VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
1395                                         *resolveDepthStencilImage, depthStencilSubresourceRange),
1396                         };
1397
1398                         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u,
1399                                 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
1400                 }
1401
1402                 // Will clear the attachments with specified depth and stencil values.
1403                 {
1404                         const VkClearValue                      clearValues[]           =
1405                                 {
1406                                         makeClearValueColor(clearColor),                                                // attachment 0
1407                                         makeClearValueDepthStencil(0.5f, 3u),                                   // attachment 1
1408                                         makeClearValueColor(clearColor),                                                // attachment 2
1409                                         makeClearValueDepthStencil(0.5f, 3u),                                   // attachment 3
1410                                 };
1411
1412                         const VkRenderPassBeginInfo     renderPassBeginInfo     =
1413                                 {
1414                                         VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,       // VkStructureType         sType;
1415                                         DE_NULL,                                                                        // const void*             pNext;
1416                                         *renderPass,                                                            // VkRenderPass            renderPass;
1417                                         *framebuffer,                                                           // VkFramebuffer           framebuffer;
1418                                         renderArea,                                                                     // VkRect2D                renderArea;
1419                                         DE_LENGTH_OF_ARRAY(clearValues),                        // deUint32                clearValueCount;
1420                                         clearValues,                                                            // const VkClearValue*     pClearValues;
1421                                 };
1422
1423                         vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
1424                 }
1425
1426                 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1427                 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
1428                 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
1429
1430                 // Mask half of the attachment image with value that will pass the stencil test.
1431                 if (m_testMode == MODE_STENCIL)
1432                         commandClearStencilAttachment(vk, *cmdBuffer, makeOffset2D(0, 0), makeExtent2D(renderSize.x()/2, renderSize.y()), 1u);
1433
1434                 vk.cmdDraw(*cmdBuffer, numVertices, 1u, 0u, 0u);
1435                 endRenderPass(vk, *cmdBuffer);
1436
1437                 copyImageToBuffer(vk, *cmdBuffer, *resolveColorImage, *colorBuffer, renderSize, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
1438                 VkImageAspectFlags dsAspect = m_testMode == MODE_DEPTH ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_STENCIL_BIT;
1439                 copyImageToBuffer(vk, *cmdBuffer, *resolveDepthStencilImage, *dsBuffer, renderSize, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, 1u, dsAspect, dsAspect);
1440
1441                 endCommandBuffer(vk, *cmdBuffer);
1442                 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1443         }
1444
1445         // Verify color output
1446         {
1447                 invalidateAlloc(vk, device, *colorBufferAlloc);
1448
1449                 const tcu::ConstPixelBufferAccess       imagePixelAccess(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1, colorBufferAlloc->getHostPtr());
1450                 const tcu::TextureLevel                         referenceImage  = generateReferenceColorImage(mapVkFormat(colorFormat), renderSize);
1451                 if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", referenceImage.getAccess(), imagePixelAccess, tcu::Vec4(0.02f), tcu::COMPARE_LOG_RESULT))
1452                         printf("Rendered color image is not correct");
1453         }
1454
1455         // Verify depth-stencil output
1456         {
1457                 invalidateAlloc(vk, device, *dsBufferAlloc);
1458                 tcu::TextureFormat format = mapVkFormat(depthStencilFormat);
1459                 const tcu::ConstPixelBufferAccess       dsPixelAccess (format, renderSize.x(), renderSize.y(), 1, dsBufferAlloc->getHostPtr());
1460
1461                 for(int z = 0; z < dsPixelAccess.getDepth(); z++)
1462                 for(int y = 0; y < dsPixelAccess.getHeight(); y++)
1463                 for(int x = 0; x < dsPixelAccess.getWidth(); x++)
1464                 {
1465                         float   depthValue              = (m_testMode == MODE_DEPTH) ? dsPixelAccess.getPixDepth(x, y, z) : 0.0f;
1466                         int             stencilValue    = (m_testMode == MODE_STENCIL) ? dsPixelAccess.getPixStencil(x, y, z) : 0;
1467
1468                         // Depth test should write to the depth buffer even when there is a discard in the fragment shader,
1469                         // when early fragment tests are enabled.
1470                         if (m_testMode == MODE_DEPTH)
1471                         {
1472                                 if (m_useEarlyTests && ((x + y) < 31) && depthValue >= 0.5f)
1473                                 {
1474                                         std::ostringstream error;
1475                                         error << "Rendered depth value [ "<< x << ", " << y << ", " << z << "] is not correct: " << depthValue << " >= 0.5f";
1476                                         TCU_FAIL(error.str().c_str());
1477                                 }
1478                                 // When early fragment tests are disabled, the depth test happens after the fragment shader, but as we are discarding
1479                                 // all fragments, the stored value in the depth buffer should be the clear one (0.5f).
1480                                 if (!m_useEarlyTests && deAbs(depthValue - 0.5f) > 0.01f)
1481                                 {
1482                                         std::ostringstream error;
1483                                         error << "Rendered depth value [ "<< x << ", " << y << ", " << z << "] is not correct: " << depthValue << " != 0.5f";
1484                                         TCU_FAIL(error.str().c_str());
1485                                 }
1486                         }
1487
1488                         if (m_testMode == MODE_STENCIL)
1489                         {
1490                                 if (m_useEarlyTests && ((x < 16 && stencilValue != 2u) || (x >= 16 && stencilValue != 4u)))
1491                                 {
1492                                         std::ostringstream error;
1493                                         error << "Rendered stencil value [ "<< x << ", " << y << ", " << z << "] is not correct: " << stencilValue << " != ";
1494                                         error << (x < 16 ? 2u : 4u);
1495                                         TCU_FAIL(error.str().c_str());
1496                                 }
1497
1498                                 if (!m_useEarlyTests && ((x < 16 && stencilValue != 1u) || (x >= 16 && stencilValue != 3u)))
1499                                 {
1500                                         std::ostringstream error;
1501                                         error << "Rendered stencil value [ "<< x << ", " << y << ", " << z << "] is not correct: " << stencilValue << " != ";
1502                                         error << (x < 16 ? 1u : 3u);
1503                                         TCU_FAIL(error.str().c_str());
1504                                 }
1505                         }
1506                 }
1507         }
1508
1509         // Verify we process all the fragments
1510         {
1511                 invalidateAlloc(vk, device, *resultBufferAlloc);
1512
1513                 const int  actualCounter           = *static_cast<deInt32*>(resultBufferAlloc->getHostPtr());
1514                 const bool expectPartialResult = m_useEarlyTests;
1515                 const int  expectedCounter         = expectPartialResult ? renderSize.x() * renderSize.y() / 2 : renderSize.x() * renderSize.y();
1516                 const int  tolerance               = expectPartialResult ? de::max(renderSize.x(), renderSize.y()) * 3  : 0;
1517                 const int  expectedMin         = de::max(0, expectedCounter - tolerance);
1518                 const int  expectedMax             = expectedCounter + tolerance;
1519
1520                 tcu::TestLog& log = m_context.getTestContext().getLog();
1521                 log << tcu::TestLog::Message << "Expected value"
1522                         << (expectPartialResult ? " in range: [" + de::toString(expectedMin) + ", " + de::toString(expectedMax) + "]" : ": " + de::toString(expectedCounter))
1523                         << tcu::TestLog::EndMessage;
1524                 log << tcu::TestLog::Message << "Result value: " << de::toString(actualCounter) << tcu::TestLog::EndMessage;
1525
1526                 if (expectedMin <= actualCounter && actualCounter <= expectedMax)
1527                         return tcu::TestStatus::pass("Success");
1528                 else
1529                         return tcu::TestStatus::fail("Value out of range");
1530         }
1531 }
1532
1533 class EarlyFragmentSampleMaskTest : public EarlyFragmentTest
1534 {
1535 public:
1536                                                 EarlyFragmentSampleMaskTest     (tcu::TestContext&              testCtx,
1537                                                                                                          const std::string              name,
1538                                                                                                          const deUint32                 flags,
1539                                                                                                          const deUint32                 sampleCount);
1540
1541         void                            initPrograms                            (SourceCollections&             programCollection) const override;
1542         TestInstance*           createInstance                          (Context&                               context) const override;
1543         void                            checkSupport                            (Context&                               context) const override;
1544
1545 private:
1546         const deUint32          m_flags;
1547         const deUint32          m_sampleCount;
1548 };
1549
1550 EarlyFragmentSampleMaskTest::EarlyFragmentSampleMaskTest (tcu::TestContext& testCtx, const std::string name, const deUint32 flags, const deUint32 sampleCount)
1551         : EarlyFragmentTest     (testCtx, name, flags)
1552         , m_flags (flags)
1553         , m_sampleCount (sampleCount)
1554 {
1555 }
1556
1557 TestInstance* EarlyFragmentSampleMaskTest::createInstance (Context& context) const
1558 {
1559         return new EarlyFragmentSampleMaskTestInstance(context, m_flags, m_sampleCount);
1560 }
1561
1562 void EarlyFragmentSampleMaskTest::initPrograms(SourceCollections &programCollection) const
1563 {
1564         // Vertex
1565         {
1566                 std::ostringstream src;
1567                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
1568                         << "\n"
1569                         << "layout(location = 0) in highp vec4 position;\n"
1570                         << "\n"
1571                         << "out gl_PerVertex {\n"
1572                         << "   vec4 gl_Position;\n"
1573                         << "};\n"
1574                         << "\n"
1575                         << "void main (void)\n"
1576                         << "{\n"
1577                         << "    gl_Position = position;\n"
1578                         << "}\n";
1579
1580                 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
1581         }
1582
1583         // Fragment
1584         {
1585                 const bool useEarlyTests = (m_flags & FLAG_DONT_USE_EARLY_FRAGMENT_TESTS) == 0;
1586                 std::ostringstream src;
1587                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
1588                         << "\n"
1589                         << (useEarlyTests ? "layout(early_fragment_tests) in;\n" : "")
1590                         << "layout(location = 0) out highp vec4 fragColor;\n"
1591                         << "\n"
1592                         << "layout(binding = 0) coherent buffer Output {\n"
1593                         << "    uint result;\n"
1594                         << "} sb_out;\n"
1595                         << "\n"
1596                         << "void main (void)\n"
1597                         << "{\n"
1598                         << "    atomicAdd(sb_out.result, 1u);\n"
1599                         << "    gl_SampleMask[0] = 0x0;\n"
1600                         << "    fragColor = vec4(1.0, 1.0, 0.0, 1.0);\n"
1601                         << "    discard;\n"
1602                         << "}\n";
1603
1604                 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
1605         }
1606 }
1607
1608 void EarlyFragmentSampleMaskTest::checkSupport(Context& context) const
1609 {
1610         EarlyFragmentTest::checkSupport(context);
1611
1612         context.requireDeviceFunctionality("VK_KHR_depth_stencil_resolve");
1613 }
1614
1615 } // anonymous ns
1616
1617 tcu::TestCaseGroup* createEarlyFragmentTests (tcu::TestContext& testCtx)
1618 {
1619         de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "early_fragment", "early fragment test cases"));
1620
1621         {
1622                 static const struct
1623                 {
1624                         std::string caseName;
1625                         deUint32        flags;
1626                 } cases[] =
1627                 {
1628                         { "no_early_fragment_tests_depth",                                      FLAG_TEST_DEPTH   | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS                                                                  },
1629                         { "no_early_fragment_tests_stencil",                            FLAG_TEST_STENCIL | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS                                                                  },
1630                         { "early_fragment_tests_depth",                                         FLAG_TEST_DEPTH                                                                                                                                                 },
1631                         { "early_fragment_tests_stencil",                                       FLAG_TEST_STENCIL                                                                                                                                               },
1632                         { "no_early_fragment_tests_depth_no_attachment",        FLAG_TEST_DEPTH   | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS | FLAG_DONT_USE_TEST_ATTACHMENT  },
1633                         { "no_early_fragment_tests_stencil_no_attachment",      FLAG_TEST_STENCIL | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS | FLAG_DONT_USE_TEST_ATTACHMENT  },
1634                         { "early_fragment_tests_depth_no_attachment",           FLAG_TEST_DEPTH   |                                                                              FLAG_DONT_USE_TEST_ATTACHMENT  },
1635                         { "early_fragment_tests_stencil_no_attachment",         FLAG_TEST_STENCIL |                                                                              FLAG_DONT_USE_TEST_ATTACHMENT  },
1636                 };
1637
1638                 for (int i = 0; i < DE_LENGTH_OF_ARRAY(cases); ++i)
1639                         testGroup->addChild(new EarlyFragmentTest(testCtx, cases[i].caseName, cases[i].flags));
1640         }
1641
1642         // Check that discard does not affect depth test writes.
1643         {
1644                 static const struct
1645                 {
1646                         std::string caseName;
1647                         deUint32        flags;
1648                 } cases[] =
1649                 {
1650                         { "discard_no_early_fragment_tests_depth",                                      FLAG_TEST_DEPTH   | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS                                                                  },
1651                         { "discard_no_early_fragment_tests_stencil",                            FLAG_TEST_STENCIL | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS                                                                  },
1652                         { "discard_early_fragment_tests_depth",                                         FLAG_TEST_DEPTH                                                                                                                                                 },
1653                         { "discard_early_fragment_tests_stencil",                                       FLAG_TEST_STENCIL                                                                                                                                               },
1654                 };
1655
1656                 for (int i = 0; i < DE_LENGTH_OF_ARRAY(cases); ++i)
1657                         testGroup->addChild(new EarlyFragmentDiscardTest(testCtx, cases[i].caseName, cases[i].flags));
1658         }
1659
1660         // Check that writing to gl_SampleMask does not affect depth test writes.
1661         {
1662                 static const struct
1663                 {
1664                         std::string caseName;
1665                         deUint32        flags;
1666                 } cases[] =
1667                 {
1668                         { "samplemask_no_early_fragment_tests_depth",                           FLAG_TEST_DEPTH   | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS,                                                                 },
1669                         { "samplemask_early_fragment_tests_depth",                                      FLAG_TEST_DEPTH,                                                                                                                                                },
1670                 };
1671
1672                 const VkSampleCountFlags sampleCounts[] = { VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_8_BIT, VK_SAMPLE_COUNT_16_BIT };
1673                 const std::string sampleCountsStr[] = { "samples_2", "samples_4", "samples_8", "samples_16" };
1674
1675                 for (deUint32 sampleCountsNdx = 0; sampleCountsNdx < DE_LENGTH_OF_ARRAY(sampleCounts); sampleCountsNdx++)
1676                 {
1677                         for (int i = 0; i < DE_LENGTH_OF_ARRAY(cases); ++i)
1678                                 testGroup->addChild(new EarlyFragmentSampleMaskTest(testCtx, cases[i].caseName + "_" + sampleCountsStr[sampleCountsNdx], cases[i].flags, sampleCounts[sampleCountsNdx]));
1679         }
1680         }
1681
1682         return testGroup.release();
1683 }
1684
1685 } // FragmentOperations
1686 } // vkt