Test behaviour of color write enable with colorWriteMask
[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
46 #include "deUniquePtr.hpp"
47 #include "deStringUtil.hpp"
48
49 #include <string>
50
51 namespace vkt
52 {
53 namespace FragmentOperations
54 {
55 namespace
56 {
57 using namespace vk;
58 using de::UniquePtr;
59
60 //! Basic 2D image.
61 inline VkImageCreateInfo makeImageCreateInfo (const tcu::IVec2& size, const VkFormat format, const VkImageUsageFlags usage)
62 {
63         const VkImageCreateInfo imageParams =
64         {
65                 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                                    // VkStructureType                      sType;
66                 DE_NULL,                                                                                                // const void*                          pNext;
67                 (VkImageCreateFlags)0,                                                                  // VkImageCreateFlags           flags;
68                 VK_IMAGE_TYPE_2D,                                                                               // VkImageType                          imageType;
69                 format,                                                                                                 // VkFormat                                     format;
70                 makeExtent3D(size.x(), size.y(), 1),                                    // VkExtent3D                           extent;
71                 1u,                                                                                                             // deUint32                                     mipLevels;
72                 1u,                                                                                                             // deUint32                                     arrayLayers;
73                 VK_SAMPLE_COUNT_1_BIT,                                                                  // VkSampleCountFlagBits        samples;
74                 VK_IMAGE_TILING_OPTIMAL,                                                                // VkImageTiling                        tiling;
75                 usage,                                                                                                  // VkImageUsageFlags            usage;
76                 VK_SHARING_MODE_EXCLUSIVE,                                                              // VkSharingMode                        sharingMode;
77                 0u,                                                                                                             // deUint32                                     queueFamilyIndexCount;
78                 DE_NULL,                                                                                                // const deUint32*                      pQueueFamilyIndices;
79                 VK_IMAGE_LAYOUT_UNDEFINED,                                                              // VkImageLayout                        initialLayout;
80         };
81         return imageParams;
82 }
83
84 Move<VkRenderPass> makeRenderPass (const DeviceInterface&       vk,
85                                                                    const VkDevice                       device,
86                                                                    const VkFormat                       colorFormat,
87                                                                    const bool                           useDepthStencilAttachment,
88                                                                    const VkFormat                       depthStencilFormat)
89 {
90         return makeRenderPass(vk, device, colorFormat, useDepthStencilAttachment ? depthStencilFormat : VK_FORMAT_UNDEFINED);
91 }
92
93 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface&   vk,
94                                                                            const VkDevice                       device,
95                                                                            const VkPipelineLayout       pipelineLayout,
96                                                                            const VkRenderPass           renderPass,
97                                                                            const VkShaderModule         vertexModule,
98                                                                            const VkShaderModule         fragmentModule,
99                                                                            const tcu::IVec2&            renderSize,
100                                                                            const bool                           enableDepthTest,
101                                                                            const bool                           enableStencilTest)
102 {
103         const std::vector<VkViewport>                   viewports                                       (1, makeViewport(renderSize));
104         const std::vector<VkRect2D>                             scissors                                        (1, makeRect2D(renderSize));
105
106         const VkStencilOpState                                  stencilOpState                          = makeStencilOpState(
107                 VK_STENCIL_OP_KEEP,             // stencil fail
108                 VK_STENCIL_OP_KEEP,             // depth & stencil pass
109                 VK_STENCIL_OP_KEEP,             // depth only fail
110                 VK_COMPARE_OP_EQUAL,    // compare op
111                 1u,                                             // compare mask
112                 1u,                                             // write mask
113                 1u);                                    // reference
114
115         VkPipelineDepthStencilStateCreateInfo   depthStencilStateCreateInfo     =
116         {
117                 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,     // VkStructureType                          sType
118                 DE_NULL,                                                                                                        // const void*                              pNext
119                 0u,                                                                                                                     // VkPipelineDepthStencilStateCreateFlags   flags
120                 enableDepthTest ? VK_TRUE : VK_FALSE,                                           // VkBool32                                 depthTestEnable
121                 enableDepthTest ? VK_TRUE : VK_FALSE,                                           // VkBool32                                 depthWriteEnable
122                 VK_COMPARE_OP_LESS,                                                                                     // VkCompareOp                              depthCompareOp
123                 VK_FALSE,                                                                                                       // VkBool32                                 depthBoundsTestEnable
124                 enableStencilTest ? VK_TRUE : VK_FALSE,                                         // VkBool32                                 stencilTestEnable
125                 stencilOpState,                                                                                         // VkStencilOpState                         front
126                 stencilOpState,                                                                                         // VkStencilOpState                         back
127                 0.0f,                                                                                                           // float                                    minDepthBounds
128                 1.0f                                                                                                            // float                                    maxDepthBounds
129         };
130
131         return vk::makeGraphicsPipeline(vk,                                                                             // const DeviceInterface&                        vk
132                                                                         device,                                                                 // const VkDevice                                device
133                                                                         pipelineLayout,                                                 // const VkPipelineLayout                        pipelineLayout
134                                                                         vertexModule,                                                   // const VkShaderModule                          vertexShaderModule
135                                                                         DE_NULL,                                                                // const VkShaderModule                          tessellationControlModule
136                                                                         DE_NULL,                                                                // const VkShaderModule                          tessellationEvalModule
137                                                                         DE_NULL,                                                                // const VkShaderModule                          geometryShaderModule
138                                                                         fragmentModule,                                                 // const VkShaderModule                          fragmentShaderModule
139                                                                         renderPass,                                                             // const VkRenderPass                            renderPass
140                                                                         viewports,                                                              // const std::vector<VkViewport>&                viewports
141                                                                         scissors,                                                               // const std::vector<VkRect2D>&                  scissors
142                                                                         VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,    // const VkPrimitiveTopology                     topology
143                                                                         0u,                                                                             // const deUint32                                subpass
144                                                                         0u,                                                                             // const deUint32                                patchControlPoints
145                                                                         DE_NULL,                                                                // const VkPipelineVertexInputStateCreateInfo*   vertexInputStateCreateInfo
146                                                                         DE_NULL,                                                                // const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
147                                                                         DE_NULL,                                                                // const VkPipelineMultisampleStateCreateInfo*   multisampleStateCreateInfo
148                                                                         &depthStencilStateCreateInfo);                  // const VkPipelineDepthStencilStateCreateInfo*  depthStencilStateCreateInfo
149 }
150
151 void commandClearStencilAttachment (const DeviceInterface&      vk,
152                                                                         const VkCommandBuffer   commandBuffer,
153                                                                         const VkOffset2D&               offset,
154                                                                         const VkExtent2D&               extent,
155                                                                         const deUint32                  clearValue)
156 {
157         const VkClearAttachment stencilAttachment =
158         {
159                 VK_IMAGE_ASPECT_STENCIL_BIT,                                    // VkImageAspectFlags    aspectMask;
160                 0u,                                                                                             // uint32_t              colorAttachment;
161                 makeClearValueDepthStencil(0.0f, clearValue),   // VkClearValue          clearValue;
162         };
163
164         const VkClearRect rect =
165         {
166                 { offset, extent },             // VkRect2D    rect;
167                 0u,                                             // uint32_t    baseArrayLayer;
168                 1u,                                             // uint32_t    layerCount;
169         };
170
171         vk.cmdClearAttachments(commandBuffer, 1u, &stencilAttachment, 1u, &rect);
172 }
173
174 VkImageAspectFlags getImageAspectFlags (const VkFormat format)
175 {
176         const tcu::TextureFormat tcuFormat = mapVkFormat(format);
177
178         if      (tcuFormat.order == tcu::TextureFormat::DS)             return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
179         else if (tcuFormat.order == tcu::TextureFormat::D)              return VK_IMAGE_ASPECT_DEPTH_BIT;
180         else if (tcuFormat.order == tcu::TextureFormat::S)              return VK_IMAGE_ASPECT_STENCIL_BIT;
181
182         DE_ASSERT(false);
183         return 0u;
184 }
185
186 bool isSupportedDepthStencilFormat (const InstanceInterface& instanceInterface, const VkPhysicalDevice device, const VkFormat format)
187 {
188         VkFormatProperties formatProps;
189         instanceInterface.getPhysicalDeviceFormatProperties(device, format, &formatProps);
190         return (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0;
191 }
192
193 VkFormat pickSupportedDepthStencilFormat (const InstanceInterface&      instanceInterface,
194                                                                                   const VkPhysicalDevice        device,
195                                                                                   const deUint32                        numFormats,
196                                                                                   const VkFormat*                       pFormats)
197 {
198         for (deUint32 i = 0; i < numFormats; ++i)
199                 if (isSupportedDepthStencilFormat(instanceInterface, device, pFormats[i]))
200                         return pFormats[i];
201         return VK_FORMAT_UNDEFINED;
202 }
203
204 enum Flags
205 {
206         FLAG_TEST_DEPTH                                                 = 1u << 0,
207         FLAG_TEST_STENCIL                                               = 1u << 1,
208         FLAG_DONT_USE_TEST_ATTACHMENT                   = 1u << 2,
209         FLAG_DONT_USE_EARLY_FRAGMENT_TESTS              = 1u << 3,
210 };
211
212 class EarlyFragmentTest : public TestCase
213 {
214 public:
215                                                 EarlyFragmentTest       (tcu::TestContext&              testCtx,
216                                                                                          const std::string              name,
217                                                                                          const deUint32                 flags);
218
219         void                            initPrograms            (SourceCollections&             programCollection) const;
220         TestInstance*           createInstance          (Context&                               context) const;
221         virtual void            checkSupport            (Context&                               context) const;
222
223 private:
224         const deUint32          m_flags;
225 };
226
227 EarlyFragmentTest::EarlyFragmentTest (tcu::TestContext& testCtx, const std::string name, const deUint32 flags)
228         : TestCase      (testCtx, name, "")
229         , m_flags       (flags)
230 {
231 }
232
233 void EarlyFragmentTest::initPrograms (SourceCollections& programCollection) const
234 {
235         // Vertex
236         {
237                 std::ostringstream src;
238                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
239                         << "\n"
240                         << "layout(location = 0) in highp vec4 position;\n"
241                         << "\n"
242                         << "out gl_PerVertex {\n"
243                         << "   vec4 gl_Position;\n"
244                         << "};\n"
245                         << "\n"
246                         << "void main (void)\n"
247                         << "{\n"
248                         << "    gl_Position = position;\n"
249                         << "}\n";
250
251                 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
252         }
253
254         // Fragment
255         {
256                 const bool useEarlyTests = (m_flags & FLAG_DONT_USE_EARLY_FRAGMENT_TESTS) == 0;
257                 std::ostringstream src;
258                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
259                         << "\n"
260                         << (useEarlyTests ? "layout(early_fragment_tests) in;\n" : "")
261                         << "layout(location = 0) out highp vec4 fragColor;\n"
262                         << "\n"
263                         << "layout(binding = 0) coherent buffer Output {\n"
264                         << "    uint result;\n"
265                         << "} sb_out;\n"
266                         << "\n"
267                         << "void main (void)\n"
268                         << "{\n"
269                         << "    atomicAdd(sb_out.result, 1u);\n"
270                         << "    fragColor = vec4(1.0, 1.0, 0.0, 1.0);\n"
271                         << "}\n";
272
273                 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
274         }
275 }
276
277 class EarlyFragmentTestInstance : public TestInstance
278 {
279 public:
280                                                         EarlyFragmentTestInstance (Context& context, const deUint32 flags);
281
282         tcu::TestStatus                 iterate                                   (void);
283
284 private:
285         enum TestMode
286         {
287                 MODE_INVALID,
288                 MODE_DEPTH,
289                 MODE_STENCIL,
290         };
291
292         const TestMode                  m_testMode;
293         const bool                              m_useTestAttachment;
294         const bool                              m_useEarlyTests;
295 };
296
297 EarlyFragmentTestInstance::EarlyFragmentTestInstance (Context& context, const deUint32 flags)
298         : TestInstance                  (context)
299         , m_testMode                    (flags & FLAG_TEST_DEPTH   ? MODE_DEPTH :
300                                                          flags & FLAG_TEST_STENCIL ? MODE_STENCIL : MODE_INVALID)
301         , m_useTestAttachment   ((flags & FLAG_DONT_USE_TEST_ATTACHMENT) == 0)
302         , m_useEarlyTests               ((flags & FLAG_DONT_USE_EARLY_FRAGMENT_TESTS) == 0)
303 {
304         DE_ASSERT(m_testMode != MODE_INVALID);
305 }
306
307 tcu::TestStatus EarlyFragmentTestInstance::iterate (void)
308 {
309         const DeviceInterface&          vk                                      = m_context.getDeviceInterface();
310         const InstanceInterface&        vki                                     = m_context.getInstanceInterface();
311         const VkDevice                          device                          = m_context.getDevice();
312         const VkPhysicalDevice          physDevice                      = m_context.getPhysicalDevice();
313         const VkQueue                           queue                           = m_context.getUniversalQueue();
314         const deUint32                          queueFamilyIndex        = m_context.getUniversalQueueFamilyIndex();
315         Allocator&                                      allocator                       = m_context.getDefaultAllocator();
316
317         // Color attachment
318
319         const tcu::IVec2                                renderSize                      = tcu::IVec2(32, 32);
320         const VkFormat                                  colorFormat                     = VK_FORMAT_R8G8B8A8_UNORM;
321         const VkImageSubresourceRange   colorSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
322         const Unique<VkImage>                   colorImage                      (makeImage(vk, device, makeImageCreateInfo(renderSize, colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
323         const UniquePtr<Allocation>             colorImageAlloc         (bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any));
324         const Unique<VkImageView>               colorImageView          (makeImageView(vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange));
325
326         // Test attachment (depth or stencil)
327         static const VkFormat stencilFormats[] =
328         {
329                 // One of the following formats must be supported, as per spec requirement.
330                 VK_FORMAT_S8_UINT,
331                 VK_FORMAT_D16_UNORM_S8_UINT,
332                 VK_FORMAT_D24_UNORM_S8_UINT,
333                 VK_FORMAT_D32_SFLOAT_S8_UINT,
334         };
335
336         const VkFormat testFormat = (m_testMode == MODE_STENCIL ? pickSupportedDepthStencilFormat(vki, physDevice, DE_LENGTH_OF_ARRAY(stencilFormats), stencilFormats)
337                                                                                                                         : VK_FORMAT_D16_UNORM);         // spec requires this format to be supported
338         if (testFormat == VK_FORMAT_UNDEFINED)
339                 return tcu::TestStatus::fail("Required depth/stencil format not supported");
340
341         if (m_useTestAttachment)
342                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Using depth/stencil format " << getFormatName(testFormat) << tcu::TestLog::EndMessage;
343
344         const VkImageSubresourceRange   testSubresourceRange    = makeImageSubresourceRange(getImageAspectFlags(testFormat), 0u, 1u, 0u, 1u);
345         const Unique<VkImage>                   testImage                               (makeImage(vk, device, makeImageCreateInfo(renderSize, testFormat, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)));
346         const UniquePtr<Allocation>             testImageAlloc                  (bindImage(vk, device, allocator, *testImage, MemoryRequirement::Any));
347         const Unique<VkImageView>               testImageView                   (makeImageView(vk, device, *testImage, VK_IMAGE_VIEW_TYPE_2D, testFormat, testSubresourceRange));
348         const VkImageView                               attachmentImages[]              = { *colorImageView, *testImageView };
349         const deUint32                                  numUsedAttachmentImages = (m_useTestAttachment ? 2u : 1u);
350
351         // Vertex buffer
352
353         const deUint32                                  numVertices                             = 6;
354         const VkDeviceSize                              vertexBufferSizeBytes   = sizeof(tcu::Vec4) * numVertices;
355         const Unique<VkBuffer>                  vertexBuffer                    (makeBuffer(vk, device, vertexBufferSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
356         const UniquePtr<Allocation>             vertexBufferAlloc               (bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible));
357
358         {
359                 tcu::Vec4* const pVertices = reinterpret_cast<tcu::Vec4*>(vertexBufferAlloc->getHostPtr());
360
361                 pVertices[0] = tcu::Vec4( 1.0f, -1.0f,  0.5f,  1.0f);
362                 pVertices[1] = tcu::Vec4(-1.0f, -1.0f,  0.0f,  1.0f);
363                 pVertices[2] = tcu::Vec4(-1.0f,  1.0f,  0.5f,  1.0f);
364
365                 pVertices[3] = tcu::Vec4(-1.0f,  1.0f,  0.5f,  1.0f);
366                 pVertices[4] = tcu::Vec4( 1.0f,  1.0f,  1.0f,  1.0f);
367                 pVertices[5] = tcu::Vec4( 1.0f, -1.0f,  0.5f,  1.0f);
368
369                 flushAlloc(vk, device, *vertexBufferAlloc);
370                 // No barrier needed, flushed memory is automatically visible
371         }
372
373         // Result buffer
374
375         const VkDeviceSize                              resultBufferSizeBytes   = sizeof(deUint32);
376         const Unique<VkBuffer>                  resultBuffer                    (makeBuffer(vk, device, resultBufferSizeBytes, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT));
377         const UniquePtr<Allocation>             resultBufferAlloc               (bindBuffer(vk, device, allocator, *resultBuffer, MemoryRequirement::HostVisible));
378
379         {
380                 deUint32* const pData = static_cast<deUint32*>(resultBufferAlloc->getHostPtr());
381
382                 *pData = 0;
383                 flushAlloc(vk, device, *resultBufferAlloc);
384         }
385
386         // Render result buffer (to retrieve color attachment contents)
387
388         const VkDeviceSize                              colorBufferSizeBytes    = tcu::getPixelSize(mapVkFormat(colorFormat)) * renderSize.x() * renderSize.y();
389         const Unique<VkBuffer>                  colorBuffer                             (makeBuffer(vk, device, colorBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
390         const UniquePtr<Allocation>             colorBufferAlloc                (bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
391
392         // Descriptors
393
394         const Unique<VkDescriptorSetLayout> descriptorSetLayout(DescriptorSetLayoutBuilder()
395                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT)
396                 .build(vk, device));
397
398         const Unique<VkDescriptorPool> descriptorPool(DescriptorPoolBuilder()
399                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
400                 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
401
402         const Unique<VkDescriptorSet> descriptorSet                              (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
403         const VkDescriptorBufferInfo  resultBufferDescriptorInfo = makeDescriptorBufferInfo(resultBuffer.get(), 0ull, resultBufferSizeBytes);
404
405         DescriptorSetUpdateBuilder()
406                 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultBufferDescriptorInfo)
407                 .update(vk, device);
408
409         // Pipeline
410
411         const Unique<VkShaderModule>    vertexModule  (createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
412         const Unique<VkShaderModule>    fragmentModule(createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u));
413         const Unique<VkRenderPass>              renderPass        (makeRenderPass(vk, device, colorFormat, m_useTestAttachment, testFormat));
414         const Unique<VkFramebuffer>             framebuffer       (makeFramebuffer(vk, device, *renderPass, numUsedAttachmentImages, attachmentImages, renderSize.x(), renderSize.y()));
415         const Unique<VkPipelineLayout>  pipelineLayout(makePipelineLayout(vk, device, *descriptorSetLayout));
416         const Unique<VkPipeline>                pipeline          (makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule, renderSize,
417                                                                                                   (m_testMode == MODE_DEPTH), (m_testMode == MODE_STENCIL)));
418         const Unique<VkCommandPool>             cmdPool           (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
419         const Unique<VkCommandBuffer>   cmdBuffer         (allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
420
421         // Draw commands
422
423         {
424                 const VkRect2D renderArea = {
425                         makeOffset2D(0, 0),
426                         makeExtent2D(renderSize.x(), renderSize.y()),
427                 };
428                 const tcu::Vec4 clearColor(0.0f, 0.0f, 0.0f, 1.0f);
429                 const VkDeviceSize vertexBufferOffset = 0ull;
430
431                 beginCommandBuffer(vk, *cmdBuffer);
432
433                 {
434                         const VkImageMemoryBarrier barriers[] = {
435                                 makeImageMemoryBarrier(
436                                         0u, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
437                                         VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
438                                         *colorImage, colorSubresourceRange),
439                                 makeImageMemoryBarrier(
440                                         0u, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
441                                         VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
442                                         *testImage, testSubresourceRange),
443                         };
444
445                         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u,
446                                 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
447                 }
448
449                 // Will clear the attachments with specified depth and stencil values.
450                 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea, clearColor, 0.5f, 0u);
451
452                 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
453                 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
454                 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
455
456                 // Mask half of the attachment image with value that will pass the stencil test.
457                 if (m_useTestAttachment && m_testMode == MODE_STENCIL)
458                         commandClearStencilAttachment(vk, *cmdBuffer, makeOffset2D(0, 0), makeExtent2D(renderSize.x()/2, renderSize.y()), 1u);
459
460                 vk.cmdDraw(*cmdBuffer, numVertices, 1u, 0u, 0u);
461                 endRenderPass(vk, *cmdBuffer);
462
463                 copyImageToBuffer(vk, *cmdBuffer, *colorImage, *colorBuffer, renderSize, VK_ACCESS_SHADER_WRITE_BIT);
464
465                 endCommandBuffer(vk, *cmdBuffer);
466                 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
467         }
468
469         // Log result image
470         {
471                 invalidateAlloc(vk, device, *colorBufferAlloc);
472
473                 const tcu::ConstPixelBufferAccess imagePixelAccess(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1, colorBufferAlloc->getHostPtr());
474
475                 tcu::TestLog& log = m_context.getTestContext().getLog();
476                 log << tcu::TestLog::Image("color0", "Rendered image", imagePixelAccess);
477         }
478
479         // Verify results
480         {
481                 invalidateAlloc(vk, device, *resultBufferAlloc);
482
483                 const int  actualCounter           = *static_cast<deInt32*>(resultBufferAlloc->getHostPtr());
484                 const bool expectPartialResult = (m_useEarlyTests && m_useTestAttachment);
485                 const int  expectedCounter         = expectPartialResult ? renderSize.x() * renderSize.y() / 2 : renderSize.x() * renderSize.y();
486                 const int  tolerance               = expectPartialResult ? de::max(renderSize.x(), renderSize.y()) * 3  : 0;
487                 const int  expectedMin         = de::max(0, expectedCounter - tolerance);
488                 const int  expectedMax             = expectedCounter + tolerance;
489
490                 tcu::TestLog& log = m_context.getTestContext().getLog();
491                 log << tcu::TestLog::Message << "Expected value"
492                         << (expectPartialResult ? " in range: [" + de::toString(expectedMin) + ", " + de::toString(expectedMax) + "]" : ": " + de::toString(expectedCounter))
493                         << tcu::TestLog::EndMessage;
494                 log << tcu::TestLog::Message << "Result value: " << de::toString(actualCounter) << tcu::TestLog::EndMessage;
495
496                 if (expectedMin <= actualCounter && actualCounter <= expectedMax)
497                         return tcu::TestStatus::pass("Success");
498                 else
499                         return tcu::TestStatus::fail("Value out of range");
500         }
501 }
502
503 TestInstance* EarlyFragmentTest::createInstance (Context& context) const
504 {
505         return new EarlyFragmentTestInstance(context, m_flags);
506 }
507
508 void EarlyFragmentTest::checkSupport (Context& context) const
509 {
510         context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_FRAGMENT_STORES_AND_ATOMICS);
511 }
512
513 } // anonymous ns
514
515 tcu::TestCaseGroup* createEarlyFragmentTests (tcu::TestContext& testCtx)
516 {
517         de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "early_fragment", "early fragment test cases"));
518
519         static const struct
520         {
521                 std::string caseName;
522                 deUint32        flags;
523         } cases[] =
524         {
525                 { "no_early_fragment_tests_depth",                                      FLAG_TEST_DEPTH   | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS                                                                  },
526                 { "no_early_fragment_tests_stencil",                            FLAG_TEST_STENCIL | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS                                                                  },
527                 { "early_fragment_tests_depth",                                         FLAG_TEST_DEPTH                                                                                                                                                 },
528                 { "early_fragment_tests_stencil",                                       FLAG_TEST_STENCIL                                                                                                                                               },
529                 { "no_early_fragment_tests_depth_no_attachment",        FLAG_TEST_DEPTH   | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS | FLAG_DONT_USE_TEST_ATTACHMENT  },
530                 { "no_early_fragment_tests_stencil_no_attachment",      FLAG_TEST_STENCIL | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS | FLAG_DONT_USE_TEST_ATTACHMENT  },
531                 { "early_fragment_tests_depth_no_attachment",           FLAG_TEST_DEPTH   |                                                                              FLAG_DONT_USE_TEST_ATTACHMENT  },
532                 { "early_fragment_tests_stencil_no_attachment",         FLAG_TEST_STENCIL |                                                                              FLAG_DONT_USE_TEST_ATTACHMENT  },
533         };
534
535         for (int i = 0; i < DE_LENGTH_OF_ARRAY(cases); ++i)
536                 testGroup->addChild(new EarlyFragmentTest(testCtx, cases[i].caseName, cases[i].flags));
537
538         return testGroup.release();
539 }
540
541 } // FragmentOperations
542 } // vkt