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 "vktTestCaseUtil.hpp"
27 
28 #include "vkDefs.hpp"
29 #include "vkRef.hpp"
30 #include "vkRefUtil.hpp"
31 #include "vkPlatform.hpp"
32 #include "vkPrograms.hpp"
33 #include "vkMemUtil.hpp"
34 #include "vkBuilderUtil.hpp"
35 #include "vkStrUtil.hpp"
36 #include "vkTypeUtil.hpp"
37 #include "vkQueryUtil.hpp"
38 #include "vkImageUtil.hpp"
39 #include "vkBarrierUtil.hpp"
40 #include "vkCmdUtil.hpp"
41 #include "vkObjUtil.hpp"
42 
43 #include "tcuTestLog.hpp"
44 #include "tcuImageCompare.hpp"
45 #include "tcuTextureUtil.hpp"
46 
47 #include "deUniquePtr.hpp"
48 #include "deStringUtil.hpp"
49 #include "deMath.h"
50 
51 #include <string>
52 
53 namespace vkt
54 {
55 namespace FragmentOperations
56 {
57 namespace
58 {
59 using namespace vk;
60 using de::UniquePtr;
61 
62 //! Basic 2D image.
makeImageCreateInfo(const tcu::IVec2 & size,const VkFormat format,const VkImageUsageFlags usage)63 inline VkImageCreateInfo makeImageCreateInfo(const tcu::IVec2 &size, const VkFormat format,
64                                              const VkImageUsageFlags usage)
65 {
66     const VkImageCreateInfo imageParams = {
67         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
68         DE_NULL,                             // const void* pNext;
69         (VkImageCreateFlags)0,               // VkImageCreateFlags flags;
70         VK_IMAGE_TYPE_2D,                    // VkImageType imageType;
71         format,                              // VkFormat format;
72         makeExtent3D(size.x(), size.y(), 1), // VkExtent3D extent;
73         1u,                                  // uint32_t mipLevels;
74         1u,                                  // uint32_t arrayLayers;
75         VK_SAMPLE_COUNT_1_BIT,               // VkSampleCountFlagBits samples;
76         VK_IMAGE_TILING_OPTIMAL,             // VkImageTiling tiling;
77         usage,                               // VkImageUsageFlags usage;
78         VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode sharingMode;
79         0u,                                  // uint32_t queueFamilyIndexCount;
80         DE_NULL,                             // const uint32_t* pQueueFamilyIndices;
81         VK_IMAGE_LAYOUT_UNDEFINED,           // VkImageLayout initialLayout;
82     };
83     return imageParams;
84 }
85 
makeRenderPass(const DeviceInterface & vk,const VkDevice device,const VkFormat colorFormat,const bool useDepthStencilAttachment,const VkFormat depthStencilFormat)86 Move<VkRenderPass> makeRenderPass(const DeviceInterface &vk, const VkDevice device, const VkFormat colorFormat,
87                                   const bool useDepthStencilAttachment, const VkFormat depthStencilFormat)
88 {
89     return makeRenderPass(vk, device, colorFormat,
90                           useDepthStencilAttachment ? depthStencilFormat : VK_FORMAT_UNDEFINED);
91 }
92 
makeGraphicsPipeline(const DeviceInterface & vk,const VkDevice device,const VkPipelineLayout pipelineLayout,const VkRenderPass renderPass,const VkShaderModule vertexModule,const VkShaderModule fragmentModule,const tcu::IVec2 & renderSize,const bool enableDepthTest,const bool enableStencilTest,const VkStencilOp stencilFailOp=VK_STENCIL_OP_KEEP,const VkStencilOp stencilPassOp=VK_STENCIL_OP_KEEP)93 Move<VkPipeline> makeGraphicsPipeline(const DeviceInterface &vk, const VkDevice device,
94                                       const VkPipelineLayout pipelineLayout, const VkRenderPass renderPass,
95                                       const VkShaderModule vertexModule, const VkShaderModule fragmentModule,
96                                       const tcu::IVec2 &renderSize, const bool enableDepthTest,
97                                       const bool enableStencilTest,
98                                       const VkStencilOp stencilFailOp = VK_STENCIL_OP_KEEP,
99                                       const VkStencilOp stencilPassOp = VK_STENCIL_OP_KEEP)
100 {
101     const std::vector<VkViewport> viewports(1, makeViewport(renderSize));
102     const std::vector<VkRect2D> scissors(1, makeRect2D(renderSize));
103 
104     const VkStencilOpState stencilOpState = makeStencilOpState(stencilFailOp,       // stencil fail
105                                                                stencilPassOp,       // depth & stencil pass
106                                                                VK_STENCIL_OP_KEEP,  // depth only fail
107                                                                VK_COMPARE_OP_EQUAL, // compare op
108                                                                0x3,                 // compare mask
109                                                                0xf,                 // write mask
110                                                                1u);                 // reference
111 
112     VkPipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo = {
113         VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType                          sType
114         DE_NULL,                                                    // const void*                              pNext
115         0u,                                                         // VkPipelineDepthStencilStateCreateFlags   flags
116         enableDepthTest ? VK_TRUE : VK_FALSE,   // VkBool32                                 depthTestEnable
117         enableDepthTest ? VK_TRUE : VK_FALSE,   // VkBool32                                 depthWriteEnable
118         VK_COMPARE_OP_LESS,                     // VkCompareOp                              depthCompareOp
119         VK_FALSE,                               // VkBool32                                 depthBoundsTestEnable
120         enableStencilTest ? VK_TRUE : VK_FALSE, // VkBool32                                 stencilTestEnable
121         stencilOpState,                         // VkStencilOpState                         front
122         stencilOpState,                         // VkStencilOpState                         back
123         0.0f,                                   // float                                    minDepthBounds
124         1.0f                                    // float                                    maxDepthBounds
125     };
126 
127     return vk::makeGraphicsPipeline(
128         vk,                                  // const DeviceInterface&                        vk
129         device,                              // const VkDevice                                device
130         pipelineLayout,                      // const VkPipelineLayout                        pipelineLayout
131         vertexModule,                        // const VkShaderModule                          vertexShaderModule
132         DE_NULL,                             // const VkShaderModule                          tessellationControlModule
133         DE_NULL,                             // const VkShaderModule                          tessellationEvalModule
134         DE_NULL,                             // const VkShaderModule                          geometryShaderModule
135         fragmentModule,                      // const VkShaderModule                          fragmentShaderModule
136         renderPass,                          // const VkRenderPass                            renderPass
137         viewports,                           // const std::vector<VkViewport>&                viewports
138         scissors,                            // const std::vector<VkRect2D>&                  scissors
139         VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // const VkPrimitiveTopology                     topology
140         0u,                                  // const uint32_t                                subpass
141         0u,                                  // const uint32_t                                patchControlPoints
142         DE_NULL,                             // const VkPipelineVertexInputStateCreateInfo*   vertexInputStateCreateInfo
143         DE_NULL,                       // const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
144         DE_NULL,                       // const VkPipelineMultisampleStateCreateInfo*   multisampleStateCreateInfo
145         &depthStencilStateCreateInfo); // const VkPipelineDepthStencilStateCreateInfo*  depthStencilStateCreateInfo
146 }
147 
commandClearStencilAttachment(const DeviceInterface & vk,const VkCommandBuffer commandBuffer,const VkOffset2D & offset,const VkExtent2D & extent,const uint32_t clearValue)148 void commandClearStencilAttachment(const DeviceInterface &vk, const VkCommandBuffer commandBuffer,
149                                    const VkOffset2D &offset, const VkExtent2D &extent, const uint32_t clearValue)
150 {
151     const VkClearAttachment stencilAttachment = {
152         VK_IMAGE_ASPECT_STENCIL_BIT,                  // VkImageAspectFlags    aspectMask;
153         0u,                                           // uint32_t              colorAttachment;
154         makeClearValueDepthStencil(0.0f, clearValue), // VkClearValue          clearValue;
155     };
156 
157     const VkClearRect rect = {
158         {offset, extent}, // VkRect2D    rect;
159         0u,               // uint32_t    baseArrayLayer;
160         1u,               // uint32_t    layerCount;
161     };
162 
163     vk.cmdClearAttachments(commandBuffer, 1u, &stencilAttachment, 1u, &rect);
164 }
165 
getImageAspectFlags(const VkFormat format)166 VkImageAspectFlags getImageAspectFlags(const VkFormat format)
167 {
168     const tcu::TextureFormat tcuFormat = mapVkFormat(format);
169 
170     if (tcuFormat.order == tcu::TextureFormat::DS)
171         return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
172     else if (tcuFormat.order == tcu::TextureFormat::D)
173         return VK_IMAGE_ASPECT_DEPTH_BIT;
174     else if (tcuFormat.order == tcu::TextureFormat::S)
175         return VK_IMAGE_ASPECT_STENCIL_BIT;
176 
177     DE_ASSERT(false);
178     return 0u;
179 }
180 
isSupportedDepthStencilFormat(const InstanceInterface & instanceInterface,const VkPhysicalDevice device,const VkFormat format)181 bool isSupportedDepthStencilFormat(const InstanceInterface &instanceInterface, const VkPhysicalDevice device,
182                                    const VkFormat format)
183 {
184     VkFormatProperties formatProps;
185     instanceInterface.getPhysicalDeviceFormatProperties(device, format, &formatProps);
186     return (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0;
187 }
188 
pickSupportedDepthStencilFormat(const InstanceInterface & instanceInterface,const VkPhysicalDevice device,const uint32_t numFormats,const VkFormat * pFormats)189 VkFormat pickSupportedDepthStencilFormat(const InstanceInterface &instanceInterface, const VkPhysicalDevice device,
190                                          const uint32_t numFormats, const VkFormat *pFormats)
191 {
192     for (uint32_t i = 0; i < numFormats; ++i)
193         if (isSupportedDepthStencilFormat(instanceInterface, device, pFormats[i]))
194             return pFormats[i];
195     return VK_FORMAT_UNDEFINED;
196 }
197 
198 enum Flags
199 {
200     FLAG_TEST_DEPTH                    = 1u << 0,
201     FLAG_TEST_STENCIL                  = 1u << 1,
202     FLAG_DONT_USE_TEST_ATTACHMENT      = 1u << 2,
203     FLAG_DONT_USE_EARLY_FRAGMENT_TESTS = 1u << 3,
204     FLAG_EARLY_AND_LATE_FRAGMENT_TESTS = 1u << 4,
205 };
206 
207 class EarlyFragmentTest : public TestCase
208 {
209 public:
210     EarlyFragmentTest(tcu::TestContext &testCtx, const std::string name, const uint32_t flags);
211 
212     void initPrograms(SourceCollections &programCollection) const;
213     TestInstance *createInstance(Context &context) const;
214     virtual void checkSupport(Context &context) const;
215 
216 private:
217     const uint32_t m_flags;
218 };
219 
EarlyFragmentTest(tcu::TestContext & testCtx,const std::string name,const uint32_t flags)220 EarlyFragmentTest::EarlyFragmentTest(tcu::TestContext &testCtx, const std::string name, const uint32_t flags)
221     : TestCase(testCtx, name)
222     , m_flags(flags)
223 {
224 }
225 
initPrograms(SourceCollections & programCollection) const226 void EarlyFragmentTest::initPrograms(SourceCollections &programCollection) const
227 {
228     // Vertex
229     {
230         std::ostringstream src;
231         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
232             << "\n"
233             << "layout(location = 0) in highp vec4 position;\n"
234             << "\n"
235             << "out gl_PerVertex {\n"
236             << "   vec4 gl_Position;\n"
237             << "};\n"
238             << "\n"
239             << "void main (void)\n"
240             << "{\n"
241             << "    gl_Position = position;\n"
242             << "}\n";
243 
244         programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
245     }
246 
247     // Fragment
248     if ((m_flags & FLAG_EARLY_AND_LATE_FRAGMENT_TESTS) == 0)
249     {
250         const bool useEarlyTests = (m_flags & FLAG_DONT_USE_EARLY_FRAGMENT_TESTS) == 0;
251         std::ostringstream src;
252         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
253             << "\n"
254             << (useEarlyTests ? "layout(early_fragment_tests) in;\n" : "")
255             << "layout(location = 0) out highp vec4 fragColor;\n"
256             << "\n"
257             << "layout(binding = 0) coherent buffer Output {\n"
258             << "    uint result;\n"
259             << "} sb_out;\n"
260             << "\n"
261             << "void main (void)\n"
262             << "{\n"
263             << "    atomicAdd(sb_out.result, 1u);\n"
264             << "    fragColor = vec4(1.0, 1.0, 0.0, 1.0);\n"
265             << "}\n";
266 
267         programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
268     }
269     else
270     {
271         const SpirVAsmBuildOptions buildOptionsSpr(programCollection.usedVulkanVersion, SPIRV_VERSION_1_3);
272         const std::string src = "; SPIR-V\n"
273                                 "; Version: 1.0\n"
274                                 "; Bound: 24\n"
275                                 "; Schema: 0\n"
276                                 "OpCapability Shader\n"
277                                 "OpExtension \"SPV_AMD_shader_early_and_late_fragment_tests\"\n"
278                                 "%1 = OpExtInstImport \"GLSL.std.450\"\n"
279                                 "OpMemoryModel Logical GLSL450\n"
280                                 "OpEntryPoint Fragment %4 \"main\" %20\n"
281                                 "OpExecutionMode %4 OriginUpperLeft\n"
282                                 "OpExecutionMode %4 EarlyAndLateFragmentTestsAMD\n"
283                                 "OpMemberDecorate %7 0 Coherent\n"
284                                 "OpMemberDecorate %7 0 Offset 0\n"
285                                 "OpDecorate %7 BufferBlock\n"
286                                 "OpDecorate %9 DescriptorSet 0\n"
287                                 "OpDecorate %9 Binding 0\n"
288                                 "OpDecorate %20 Location 0\n"
289                                 "%2 = OpTypeVoid\n"
290                                 "%3 = OpTypeFunction %2\n"
291                                 "%6 = OpTypeInt 32 0\n"
292                                 "%7 = OpTypeStruct %6\n"
293                                 "%8 = OpTypePointer Uniform %7\n"
294                                 "%9 = OpVariable %8 Uniform\n"
295                                 "%10 = OpTypeInt 32 1\n"
296                                 "%11 = OpConstant %10 0\n"
297                                 "%12 = OpTypePointer Uniform %6\n"
298                                 "%14 = OpConstant %6 1\n"
299                                 "%15 = OpConstant %6 0\n"
300                                 "%17 = OpTypeFloat 32\n"
301                                 "%18 = OpTypeVector %17 4\n"
302                                 "%19 = OpTypePointer Output %18\n"
303                                 "%20 = OpVariable %19 Output\n"
304                                 "%21 = OpConstant %17 1\n"
305                                 "%22 = OpConstant %17 0\n"
306                                 "%23 = OpConstantComposite %18 %21 %21 %22 %21\n"
307                                 "%4 = OpFunction %2 None %3\n"
308                                 "%5 = OpLabel\n"
309                                 "%13 = OpAccessChain %12 %9 %11\n"
310                                 "%16 = OpAtomicIAdd %6 %13 %14 %15 %14\n"
311                                 "OpStore %20 %23\n"
312                                 "OpReturn\n"
313                                 "OpFunctionEnd\n";
314         programCollection.spirvAsmSources.add("frag") << src << buildOptionsSpr;
315     }
316 }
317 
318 class EarlyFragmentTestInstance : public TestInstance
319 {
320 public:
321     EarlyFragmentTestInstance(Context &context, const uint32_t flags);
322 
323     tcu::TestStatus iterate(void);
324 
325 private:
326     enum TestMode
327     {
328         MODE_INVALID,
329         MODE_DEPTH,
330         MODE_STENCIL,
331     };
332 
333     const TestMode m_testMode;
334     const bool m_useTestAttachment;
335     const bool m_useEarlyTests;
336     const bool m_useEarlyLateTests;
337 };
338 
EarlyFragmentTestInstance(Context & context,const uint32_t flags)339 EarlyFragmentTestInstance::EarlyFragmentTestInstance(Context &context, const uint32_t flags)
340     : TestInstance(context)
341     , m_testMode(flags & FLAG_TEST_DEPTH   ? MODE_DEPTH :
342                  flags & FLAG_TEST_STENCIL ? MODE_STENCIL :
343                                              MODE_INVALID)
344     , m_useTestAttachment((flags & FLAG_DONT_USE_TEST_ATTACHMENT) == 0)
345     , m_useEarlyTests((flags & FLAG_DONT_USE_EARLY_FRAGMENT_TESTS) == 0)
346     , m_useEarlyLateTests((flags & FLAG_EARLY_AND_LATE_FRAGMENT_TESTS) == FLAG_EARLY_AND_LATE_FRAGMENT_TESTS)
347 {
348     DE_ASSERT(m_testMode != MODE_INVALID);
349 }
350 
iterate(void)351 tcu::TestStatus EarlyFragmentTestInstance::iterate(void)
352 {
353     const DeviceInterface &vk         = m_context.getDeviceInterface();
354     const InstanceInterface &vki      = m_context.getInstanceInterface();
355     const VkDevice device             = m_context.getDevice();
356     const VkPhysicalDevice physDevice = m_context.getPhysicalDevice();
357     const VkQueue queue               = m_context.getUniversalQueue();
358     const uint32_t queueFamilyIndex   = m_context.getUniversalQueueFamilyIndex();
359     Allocator &allocator              = m_context.getDefaultAllocator();
360 
361     // Color attachment
362 
363     const tcu::IVec2 renderSize = tcu::IVec2(32, 32);
364     const VkFormat colorFormat  = VK_FORMAT_R8G8B8A8_UNORM;
365     const VkImageSubresourceRange colorSubresourceRange =
366         makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
367     const Unique<VkImage> colorImage(
368         makeImage(vk, device,
369                   makeImageCreateInfo(renderSize, colorFormat,
370                                       VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
371     const UniquePtr<Allocation> colorImageAlloc(bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any));
372     const Unique<VkImageView> colorImageView(
373         makeImageView(vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange));
374 
375     // Test attachment (depth or stencil)
376     static const VkFormat stencilFormats[] = {
377         // One of the following formats must be supported, as per spec requirement.
378         VK_FORMAT_S8_UINT,
379         VK_FORMAT_D16_UNORM_S8_UINT,
380         VK_FORMAT_D24_UNORM_S8_UINT,
381         VK_FORMAT_D32_SFLOAT_S8_UINT,
382     };
383 
384     const VkFormat testFormat =
385         (m_testMode == MODE_STENCIL ?
386              pickSupportedDepthStencilFormat(vki, physDevice, DE_LENGTH_OF_ARRAY(stencilFormats), stencilFormats) :
387              VK_FORMAT_D16_UNORM); // spec requires this format to be supported
388     if (testFormat == VK_FORMAT_UNDEFINED)
389         return tcu::TestStatus::fail("Required depth/stencil format not supported");
390 
391     if (m_useTestAttachment)
392         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Using depth/stencil format "
393                                             << getFormatName(testFormat) << tcu::TestLog::EndMessage;
394 
395     const VkImageSubresourceRange testSubresourceRange =
396         makeImageSubresourceRange(getImageAspectFlags(testFormat), 0u, 1u, 0u, 1u);
397     const Unique<VkImage> testImage(makeImage(
398         vk, device, makeImageCreateInfo(renderSize, testFormat, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)));
399     const UniquePtr<Allocation> testImageAlloc(bindImage(vk, device, allocator, *testImage, MemoryRequirement::Any));
400     const Unique<VkImageView> testImageView(
401         makeImageView(vk, device, *testImage, VK_IMAGE_VIEW_TYPE_2D, testFormat, testSubresourceRange));
402     const VkImageView attachmentImages[]   = {*colorImageView, *testImageView};
403     const uint32_t numUsedAttachmentImages = (m_useTestAttachment ? 2u : 1u);
404 
405     // Vertex buffer
406 
407     const uint32_t numVertices               = 6;
408     const VkDeviceSize vertexBufferSizeBytes = sizeof(tcu::Vec4) * numVertices;
409     const Unique<VkBuffer> vertexBuffer(
410         makeBuffer(vk, device, vertexBufferSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
411     const UniquePtr<Allocation> vertexBufferAlloc(
412         bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible));
413 
414     {
415         tcu::Vec4 *const pVertices = reinterpret_cast<tcu::Vec4 *>(vertexBufferAlloc->getHostPtr());
416 
417         // A small +0.00001f adjustment for the z-coordinate to get the expected rounded value for depth.
418         pVertices[0] = tcu::Vec4(1.0f, -1.0f, 0.50001f, 1.0f);
419         pVertices[1] = tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f);
420         pVertices[2] = tcu::Vec4(-1.0f, 1.0f, 0.50001f, 1.0f);
421 
422         pVertices[3] = tcu::Vec4(-1.0f, 1.0f, 0.50001f, 1.0f);
423         pVertices[4] = tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f);
424         pVertices[5] = tcu::Vec4(1.0f, -1.0f, 0.50001f, 1.0f);
425 
426         flushAlloc(vk, device, *vertexBufferAlloc);
427         // No barrier needed, flushed memory is automatically visible
428     }
429 
430     // Result buffer
431 
432     const VkDeviceSize resultBufferSizeBytes = sizeof(uint32_t);
433     const Unique<VkBuffer> resultBuffer(
434         makeBuffer(vk, device, resultBufferSizeBytes, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT));
435     const UniquePtr<Allocation> resultBufferAlloc(
436         bindBuffer(vk, device, allocator, *resultBuffer, MemoryRequirement::HostVisible));
437 
438     {
439         uint32_t *const pData = static_cast<uint32_t *>(resultBufferAlloc->getHostPtr());
440 
441         *pData = 0;
442         flushAlloc(vk, device, *resultBufferAlloc);
443     }
444 
445     // Render result buffer (to retrieve color attachment contents)
446 
447     const VkDeviceSize colorBufferSizeBytes =
448         tcu::getPixelSize(mapVkFormat(colorFormat)) * renderSize.x() * renderSize.y();
449     const Unique<VkBuffer> colorBuffer(makeBuffer(vk, device, colorBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
450     const UniquePtr<Allocation> colorBufferAlloc(
451         bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
452 
453     // Descriptors
454 
455     const Unique<VkDescriptorSetLayout> descriptorSetLayout(
456         DescriptorSetLayoutBuilder()
457             .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT)
458             .build(vk, device));
459 
460     const Unique<VkDescriptorPool> descriptorPool(
461         DescriptorPoolBuilder()
462             .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
463             .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
464 
465     const Unique<VkDescriptorSet> descriptorSet(makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
466     const VkDescriptorBufferInfo resultBufferDescriptorInfo =
467         makeDescriptorBufferInfo(resultBuffer.get(), 0ull, resultBufferSizeBytes);
468 
469     DescriptorSetUpdateBuilder()
470         .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
471                      VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultBufferDescriptorInfo)
472         .update(vk, device);
473 
474     // Pipeline
475 
476     const Unique<VkShaderModule> vertexModule(
477         createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
478     const Unique<VkShaderModule> fragmentModule(
479         createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u));
480     const Unique<VkRenderPass> renderPass(makeRenderPass(vk, device, colorFormat, m_useTestAttachment, testFormat));
481     const Unique<VkFramebuffer> framebuffer(makeFramebuffer(vk, device, *renderPass, numUsedAttachmentImages,
482                                                             attachmentImages, renderSize.x(), renderSize.y()));
483     const Unique<VkPipelineLayout> pipelineLayout(makePipelineLayout(vk, device, *descriptorSetLayout));
484     const Unique<VkPipeline> pipeline(makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule,
485                                                            *fragmentModule, renderSize, (m_testMode == MODE_DEPTH),
486                                                            (m_testMode == MODE_STENCIL)));
487     const Unique<VkCommandPool> cmdPool(
488         createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
489     const Unique<VkCommandBuffer> cmdBuffer(
490         allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
491 
492     // Draw commands
493 
494     {
495         const VkRect2D renderArea = {
496             makeOffset2D(0, 0),
497             makeExtent2D(renderSize.x(), renderSize.y()),
498         };
499         const tcu::Vec4 clearColor(0.0f, 0.0f, 0.0f, 1.0f);
500         const VkDeviceSize vertexBufferOffset = 0ull;
501 
502         beginCommandBuffer(vk, *cmdBuffer);
503 
504         {
505             const VkImageMemoryBarrier barriers[] = {
506                 makeImageMemoryBarrier(0u, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
507                                        VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, *colorImage, colorSubresourceRange),
508                 makeImageMemoryBarrier(0u, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
509                                        VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, *testImage,
510                                        testSubresourceRange),
511             };
512 
513             vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT,
514                                   VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
515                                       VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
516                                   0u, 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
517         }
518 
519         // Will clear the attachments with specified depth and stencil values.
520         beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea, clearColor, 0.5f, 0u);
521 
522         vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
523         vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u,
524                                  &descriptorSet.get(), 0u, DE_NULL);
525         vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
526 
527         // Mask half of the attachment image with value that will pass the stencil test.
528         if (m_useTestAttachment && m_testMode == MODE_STENCIL)
529             commandClearStencilAttachment(vk, *cmdBuffer, makeOffset2D(0, 0),
530                                           makeExtent2D(renderSize.x() / 2, renderSize.y()), 1u);
531 
532         vk.cmdDraw(*cmdBuffer, numVertices, 1u, 0u, 0u);
533         endRenderPass(vk, *cmdBuffer);
534 
535         copyImageToBuffer(vk, *cmdBuffer, *colorImage, *colorBuffer, renderSize, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
536 
537         endCommandBuffer(vk, *cmdBuffer);
538         submitCommandsAndWait(vk, device, queue, *cmdBuffer);
539     }
540 
541     // Log result image
542     {
543         invalidateAlloc(vk, device, *colorBufferAlloc);
544 
545         const tcu::ConstPixelBufferAccess imagePixelAccess(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1,
546                                                            colorBufferAlloc->getHostPtr());
547         tcu::TextureLevel referenceImage(mapVkFormat(colorFormat), renderSize.x(), renderSize.y());
548 
549         if (m_useTestAttachment == true)
550         {
551             const tcu::Vec4 fillColor  = tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f);
552             const tcu::Vec4 clearColor = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
553 
554             tcu::clear(referenceImage.getAccess(), clearColor);
555 
556             if (m_testMode == MODE_DEPTH)
557             {
558                 int xOffset = 0;
559 
560                 for (int y = 0; y < renderSize.y() - 1; y++)
561                 {
562                     for (int x = 0; x < renderSize.x() - 1 - xOffset; x++)
563                     {
564                         referenceImage.getAccess().setPixel(fillColor, x, y);
565                     }
566 
567                     xOffset++;
568                 }
569             }
570 
571             if (m_testMode == MODE_STENCIL)
572             {
573                 for (int y = 0; y < renderSize.y(); y++)
574                 {
575                     for (int x = 0; x < renderSize.x() / 2; x++)
576                     {
577                         referenceImage.getAccess().setPixel(fillColor, x, y);
578                     }
579                 }
580             }
581         }
582         else
583         {
584             const tcu::Vec4 clearColor = tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f);
585 
586             tcu::clear(referenceImage.getAccess(), clearColor);
587         }
588 
589         if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison",
590                                         referenceImage.getAccess(), imagePixelAccess, tcu::Vec4(0.02f),
591                                         tcu::COMPARE_LOG_RESULT))
592             return tcu::TestStatus::fail("Rendered color image is not correct");
593     }
594 
595     // Verify results
596     {
597         invalidateAlloc(vk, device, *resultBufferAlloc);
598 
599         const int actualCounter        = *static_cast<int32_t *>(resultBufferAlloc->getHostPtr());
600         const bool expectPartialResult = (m_useEarlyTests && m_useTestAttachment);
601         const int expectedCounter =
602             expectPartialResult ? renderSize.x() * renderSize.y() / 2 : renderSize.x() * renderSize.y();
603         const int tolerance   = expectPartialResult ? de::max(renderSize.x(), renderSize.y()) * 3 : 0;
604         const int expectedMin = de::max(0, expectedCounter - tolerance);
605         const int expectedMax =
606             (m_useEarlyLateTests ? (renderSize.x() * renderSize.y()) : (expectedCounter + tolerance));
607 
608         tcu::TestLog &log = m_context.getTestContext().getLog();
609         log << tcu::TestLog::Message << "Expected value"
610             << (expectPartialResult ?
611                     " in range: [" + de::toString(expectedMin) + ", " + de::toString(expectedMax) + "]" :
612                     ": " + de::toString(expectedCounter))
613             << tcu::TestLog::EndMessage;
614         log << tcu::TestLog::Message << "Result value: " << de::toString(actualCounter) << tcu::TestLog::EndMessage;
615 
616         if (expectedMin <= actualCounter && actualCounter <= expectedMax)
617             return tcu::TestStatus::pass("Success");
618         else
619             return tcu::TestStatus::fail("Value out of range");
620     }
621 }
622 
createInstance(Context & context) const623 TestInstance *EarlyFragmentTest::createInstance(Context &context) const
624 {
625     return new EarlyFragmentTestInstance(context, m_flags);
626 }
627 
checkSupport(Context & context) const628 void EarlyFragmentTest::checkSupport(Context &context) const
629 {
630     context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_FRAGMENT_STORES_AND_ATOMICS);
631 #ifndef CTS_USES_VULKANSC
632     if ((m_flags & FLAG_EARLY_AND_LATE_FRAGMENT_TESTS) == FLAG_EARLY_AND_LATE_FRAGMENT_TESTS)
633     {
634         context.requireDeviceFunctionality("VK_AMD_shader_early_and_late_fragment_tests");
635         if (context.getShaderEarlyAndLateFragmentTestsFeaturesAMD().shaderEarlyAndLateFragmentTests == VK_FALSE)
636             TCU_THROW(NotSupportedError, "shaderEarlyAndLateFragmentTests is not supported");
637     }
638 #endif
639 }
640 
641 class EarlyFragmentDiscardTestInstance : public EarlyFragmentTestInstance
642 {
643 public:
644     EarlyFragmentDiscardTestInstance(Context &context, const uint32_t flags);
645 
646     tcu::TestStatus iterate(void);
647 
648 private:
649     tcu::TextureLevel generateReferenceColorImage(const tcu::TextureFormat format, const tcu::IVec2 &renderSize);
650     enum TestMode
651     {
652         MODE_INVALID,
653         MODE_DEPTH,
654         MODE_STENCIL,
655     };
656 
657     const TestMode m_testMode;
658     const bool m_useTestAttachment;
659     const bool m_useEarlyTests;
660     const bool m_useEarlyLateTests;
661 };
662 
EarlyFragmentDiscardTestInstance(Context & context,const uint32_t flags)663 EarlyFragmentDiscardTestInstance::EarlyFragmentDiscardTestInstance(Context &context, const uint32_t flags)
664     : EarlyFragmentTestInstance(context, flags)
665     , m_testMode(flags & FLAG_TEST_DEPTH   ? MODE_DEPTH :
666                  flags & FLAG_TEST_STENCIL ? MODE_STENCIL :
667                                              MODE_INVALID)
668     , m_useTestAttachment((flags & FLAG_DONT_USE_TEST_ATTACHMENT) == 0)
669     , m_useEarlyTests((flags & FLAG_DONT_USE_EARLY_FRAGMENT_TESTS) == 0)
670     , m_useEarlyLateTests((flags & FLAG_EARLY_AND_LATE_FRAGMENT_TESTS) != 0)
671 {
672     DE_ASSERT(m_testMode != MODE_INVALID);
673 }
674 
generateReferenceColorImage(const tcu::TextureFormat format,const tcu::IVec2 & renderSize)675 tcu::TextureLevel EarlyFragmentDiscardTestInstance::generateReferenceColorImage(const tcu::TextureFormat format,
676                                                                                 const tcu::IVec2 &renderSize)
677 {
678     tcu::TextureLevel image(format, renderSize.x(), renderSize.y());
679     const tcu::Vec4 clearColor = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
680 
681     tcu::clear(image.getAccess(), clearColor);
682 
683     return image;
684 }
685 
iterate(void)686 tcu::TestStatus EarlyFragmentDiscardTestInstance::iterate(void)
687 {
688     const DeviceInterface &vk         = m_context.getDeviceInterface();
689     const InstanceInterface &vki      = m_context.getInstanceInterface();
690     const VkDevice device             = m_context.getDevice();
691     const VkPhysicalDevice physDevice = m_context.getPhysicalDevice();
692     const VkQueue queue               = m_context.getUniversalQueue();
693     const uint32_t queueFamilyIndex   = m_context.getUniversalQueueFamilyIndex();
694     Allocator &allocator              = m_context.getDefaultAllocator();
695 
696     DE_ASSERT(m_useTestAttachment);
697 
698     // Color attachment
699     const tcu::IVec2 renderSize = tcu::IVec2(32, 32);
700     const VkFormat colorFormat  = VK_FORMAT_R8G8B8A8_UNORM;
701     const VkImageSubresourceRange colorSubresourceRange =
702         makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
703     const Unique<VkImage> colorImage(
704         makeImage(vk, device,
705                   makeImageCreateInfo(renderSize, colorFormat,
706                                       VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
707     const UniquePtr<Allocation> colorImageAlloc(bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any));
708     const Unique<VkImageView> colorImageView(
709         makeImageView(vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange));
710 
711     // Test attachment (depth or stencil)
712     static const VkFormat stencilFormats[] = {
713         // One of the following formats must be supported, as per spec requirement.
714         VK_FORMAT_S8_UINT,
715         VK_FORMAT_D16_UNORM_S8_UINT,
716         VK_FORMAT_D24_UNORM_S8_UINT,
717         VK_FORMAT_D32_SFLOAT_S8_UINT,
718     };
719 
720     const VkFormat depthStencilFormat =
721         (m_testMode == MODE_STENCIL ?
722              pickSupportedDepthStencilFormat(vki, physDevice, DE_LENGTH_OF_ARRAY(stencilFormats), stencilFormats) :
723              VK_FORMAT_D16_UNORM); // spec requires this format to be supported
724 
725     if (depthStencilFormat == VK_FORMAT_UNDEFINED)
726         return tcu::TestStatus::fail("Required depth/stencil format not supported");
727 
728     m_context.getTestContext().getLog() << tcu::TestLog::Message << "Using depth/stencil format "
729                                         << getFormatName(depthStencilFormat) << tcu::TestLog::EndMessage;
730 
731     const VkImageSubresourceRange testSubresourceRange =
732         makeImageSubresourceRange(getImageAspectFlags(depthStencilFormat), 0u, 1u, 0u, 1u);
733     const Unique<VkImage> testImage(
734         makeImage(vk, device,
735                   makeImageCreateInfo(renderSize, depthStencilFormat,
736                                       VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
737     const UniquePtr<Allocation> testImageAlloc(bindImage(vk, device, allocator, *testImage, MemoryRequirement::Any));
738     const Unique<VkImageView> testImageView(
739         makeImageView(vk, device, *testImage, VK_IMAGE_VIEW_TYPE_2D, depthStencilFormat, testSubresourceRange));
740     const VkImageView attachmentImages[]   = {*colorImageView, *testImageView};
741     const uint32_t numUsedAttachmentImages = DE_LENGTH_OF_ARRAY(attachmentImages);
742 
743     // Vertex buffer
744 
745     const uint32_t numVertices               = 6;
746     const VkDeviceSize vertexBufferSizeBytes = sizeof(tcu::Vec4) * numVertices;
747     const Unique<VkBuffer> vertexBuffer(
748         makeBuffer(vk, device, vertexBufferSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
749     const UniquePtr<Allocation> vertexBufferAlloc(
750         bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible));
751 
752     {
753         tcu::Vec4 *const pVertices = reinterpret_cast<tcu::Vec4 *>(vertexBufferAlloc->getHostPtr());
754 
755         pVertices[0] = tcu::Vec4(1.0f, -1.0f, 0.5f, 1.0f);
756         pVertices[1] = tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f);
757         pVertices[2] = tcu::Vec4(-1.0f, 1.0f, 0.5f, 1.0f);
758 
759         pVertices[3] = tcu::Vec4(-1.0f, 1.0f, 0.5f, 1.0f);
760         pVertices[4] = tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f);
761         pVertices[5] = tcu::Vec4(1.0f, -1.0f, 0.5f, 1.0f);
762 
763         flushAlloc(vk, device, *vertexBufferAlloc);
764         // No barrier needed, flushed memory is automatically visible
765     }
766 
767     // Result buffer
768 
769     const VkDeviceSize resultBufferSizeBytes = sizeof(uint32_t);
770     const Unique<VkBuffer> resultBuffer(
771         makeBuffer(vk, device, resultBufferSizeBytes, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT));
772     const UniquePtr<Allocation> resultBufferAlloc(
773         bindBuffer(vk, device, allocator, *resultBuffer, MemoryRequirement::HostVisible));
774 
775     {
776         uint32_t *const pData = static_cast<uint32_t *>(resultBufferAlloc->getHostPtr());
777 
778         *pData = 0;
779         flushAlloc(vk, device, *resultBufferAlloc);
780     }
781 
782     // Render result buffer (to retrieve color attachment contents)
783 
784     const VkDeviceSize colorBufferSizeBytes =
785         tcu::getPixelSize(mapVkFormat(colorFormat)) * renderSize.x() * renderSize.y();
786     const Unique<VkBuffer> colorBuffer(makeBuffer(vk, device, colorBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
787     const UniquePtr<Allocation> colorBufferAlloc(
788         bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
789 
790     // Depth stencil result buffer (to retrieve depth-stencil attachment contents)
791 
792     const VkDeviceSize dsBufferSizeBytes =
793         tcu::getPixelSize(mapVkFormat(depthStencilFormat)) * renderSize.x() * renderSize.y();
794     const Unique<VkBuffer> dsBuffer(makeBuffer(vk, device, dsBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
795     const UniquePtr<Allocation> dsBufferAlloc(
796         bindBuffer(vk, device, allocator, *dsBuffer, MemoryRequirement::HostVisible));
797 
798     // Descriptors
799 
800     const Unique<VkDescriptorSetLayout> descriptorSetLayout(
801         DescriptorSetLayoutBuilder()
802             .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT)
803             .build(vk, device));
804 
805     const Unique<VkDescriptorPool> descriptorPool(
806         DescriptorPoolBuilder()
807             .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
808             .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
809 
810     const Unique<VkDescriptorSet> descriptorSet(makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
811     const VkDescriptorBufferInfo resultBufferDescriptorInfo =
812         makeDescriptorBufferInfo(resultBuffer.get(), 0ull, resultBufferSizeBytes);
813 
814     DescriptorSetUpdateBuilder()
815         .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
816                      VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultBufferDescriptorInfo)
817         .update(vk, device);
818 
819     // Pipeline
820 
821     const Unique<VkShaderModule> vertexModule(
822         createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
823     const Unique<VkShaderModule> fragmentModule(
824         createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u));
825     const Unique<VkRenderPass> renderPass(
826         makeRenderPass(vk, device, colorFormat, m_useTestAttachment, depthStencilFormat));
827     const Unique<VkFramebuffer> framebuffer(makeFramebuffer(vk, device, *renderPass, numUsedAttachmentImages,
828                                                             attachmentImages, renderSize.x(), renderSize.y()));
829     const Unique<VkPipelineLayout> pipelineLayout(makePipelineLayout(vk, device, *descriptorSetLayout));
830     const Unique<VkPipeline> pipeline(
831         makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule, renderSize,
832                              (m_testMode == MODE_DEPTH), (m_testMode == MODE_STENCIL),
833                              VK_STENCIL_OP_INCREMENT_AND_CLAMP, VK_STENCIL_OP_INCREMENT_AND_CLAMP));
834     const Unique<VkCommandPool> cmdPool(
835         createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
836     const Unique<VkCommandBuffer> cmdBuffer(
837         allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
838 
839     // Draw commands
840     {
841         const VkRect2D renderArea = {
842             makeOffset2D(0, 0),
843             makeExtent2D(renderSize.x(), renderSize.y()),
844         };
845         const tcu::Vec4 clearColor(0.0f, 0.0f, 0.0f, 1.0f);
846         const VkDeviceSize vertexBufferOffset = 0ull;
847 
848         beginCommandBuffer(vk, *cmdBuffer);
849 
850         {
851             const VkImageMemoryBarrier barriers[] = {
852                 makeImageMemoryBarrier(0u, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
853                                        VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, *colorImage, colorSubresourceRange),
854                 makeImageMemoryBarrier(0u, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
855                                        VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, *testImage,
856                                        testSubresourceRange),
857             };
858 
859             vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT,
860                                   VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
861                                       VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
862                                   0u, 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
863         }
864 
865         // Will clear the attachments with specified depth and stencil values.
866         beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea, clearColor, 0.5f, 3u);
867 
868         vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
869         vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u,
870                                  &descriptorSet.get(), 0u, DE_NULL);
871         vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
872 
873         // Mask half of the attachment image with value that will pass the stencil test.
874         if (m_testMode == MODE_STENCIL)
875             commandClearStencilAttachment(vk, *cmdBuffer, makeOffset2D(0, 0),
876                                           makeExtent2D(renderSize.x() / 2, renderSize.y()), 1u);
877 
878         vk.cmdDraw(*cmdBuffer, numVertices, 1u, 0u, 0u);
879         endRenderPass(vk, *cmdBuffer);
880 
881         copyImageToBuffer(vk, *cmdBuffer, *colorImage, *colorBuffer, renderSize, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
882         VkImageAspectFlags dsAspect =
883             m_testMode == MODE_DEPTH ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_STENCIL_BIT;
884         VkImageLayout dsImageLayout = m_testMode == MODE_DEPTH ? VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL :
885                                                                  VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL;
886         copyImageToBuffer(vk, *cmdBuffer, *testImage, *dsBuffer, renderSize,
887                           VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, dsImageLayout, 1u, dsAspect, dsAspect);
888 
889         endCommandBuffer(vk, *cmdBuffer);
890         submitCommandsAndWait(vk, device, queue, *cmdBuffer);
891     }
892 
893     // Verify color output
894     {
895         invalidateAlloc(vk, device, *colorBufferAlloc);
896 
897         const tcu::ConstPixelBufferAccess imagePixelAccess(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1,
898                                                            colorBufferAlloc->getHostPtr());
899         const tcu::TextureLevel referenceImage = generateReferenceColorImage(mapVkFormat(colorFormat), renderSize);
900         if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison",
901                                         referenceImage.getAccess(), imagePixelAccess, tcu::Vec4(0.02f),
902                                         tcu::COMPARE_LOG_RESULT))
903             printf("Rendered color image is not correct");
904     }
905 
906     // Verify depth-stencil output
907     {
908         invalidateAlloc(vk, device, *dsBufferAlloc);
909         // the buffer holds only one aspect of d/s format
910         tcu::TextureFormat format =
911             vk::mapVkFormat(m_testMode == MODE_STENCIL ? VK_FORMAT_S8_UINT : depthStencilFormat);
912         DE_ASSERT(format.order == tcu::TextureFormat::D || format.order == tcu::TextureFormat::S);
913 
914         const tcu::ConstPixelBufferAccess dsPixelAccess(format, renderSize.x(), renderSize.y(), 1,
915                                                         dsBufferAlloc->getHostPtr());
916 
917         for (int z = 0; z < dsPixelAccess.getDepth(); z++)
918             for (int y = 0; y < dsPixelAccess.getHeight(); y++)
919                 for (int x = 0; x < dsPixelAccess.getWidth(); x++)
920                 {
921                     float depthValue = (m_testMode == MODE_DEPTH) ? dsPixelAccess.getPixDepth(x, y, z) : 0.0f;
922                     int stencilValue = (m_testMode == MODE_STENCIL) ? dsPixelAccess.getPixStencil(x, y, z) : 0;
923 
924                     // Depth test should write to the depth buffer even when there is a discard in the fragment shader,
925                     // when early fragment tests are enabled. We allow some tolerance to account for precision error
926                     // on depth writes.
927                     if (m_testMode == MODE_DEPTH)
928                     {
929                         float tolerance = 0.0001f;
930                         if (m_useEarlyTests && ((x + y) < 31) && depthValue >= 0.50 + tolerance)
931                         {
932                             std::ostringstream error;
933                             error << "Rendered depth value [ " << x << ", " << y << ", " << z
934                                   << "] is not correct: " << depthValue << " >= 0.5f";
935                             TCU_FAIL(error.str().c_str());
936                         }
937                         // When early fragment tests are disabled, the depth test happens after the fragment shader, but as we are discarding
938                         // all fragments, the stored value in the depth buffer should be the clear one (0.5f).
939                         if (!m_useEarlyTests && deAbs(depthValue - 0.5f) > tolerance)
940                         {
941                             std::ostringstream error;
942                             error << "Rendered depth value [ " << x << ", " << y << ", " << z
943                                   << "] is not correct: " << depthValue << " != 0.5f";
944                             TCU_FAIL(error.str().c_str());
945                         }
946                     }
947 
948                     if (m_testMode == MODE_STENCIL)
949                     {
950                         if (m_useEarlyTests && ((x < 16 && stencilValue != 2u) || (x >= 16 && stencilValue != 4u)))
951                         {
952                             std::ostringstream error;
953                             error << "Rendered stencil value [ " << x << ", " << y << ", " << z
954                                   << "] is not correct: " << stencilValue << " != ";
955                             error << (x < 16 ? 2u : 4u);
956                             TCU_FAIL(error.str().c_str());
957                         }
958 
959                         if (!m_useEarlyTests && ((x < 16 && stencilValue != 1u) || (x >= 16 && stencilValue != 3u)))
960                         {
961                             std::ostringstream error;
962                             error << "Rendered stencil value [ " << x << ", " << y << ", " << z
963                                   << "] is not correct: " << stencilValue << " != ";
964                             error << (x < 16 ? 1u : 3u);
965                             TCU_FAIL(error.str().c_str());
966                         }
967                     }
968                 }
969     }
970 
971     // Verify we process all the fragments
972     {
973         invalidateAlloc(vk, device, *resultBufferAlloc);
974 
975         const int actualCounter        = *static_cast<int32_t *>(resultBufferAlloc->getHostPtr());
976         const bool expectPartialResult = m_useEarlyTests;
977         const int expectedCounter =
978             expectPartialResult ? renderSize.x() * renderSize.y() / 2 : renderSize.x() * renderSize.y();
979         const int tolerance   = expectPartialResult ? de::max(renderSize.x(), renderSize.y()) * 3 : 0;
980         const int expectedMin = de::max(0, expectedCounter - tolerance);
981         const int expectedMax =
982             (m_useEarlyLateTests ? (renderSize.x() * renderSize.y()) : (expectedCounter + tolerance));
983 
984         tcu::TestLog &log = m_context.getTestContext().getLog();
985         log << tcu::TestLog::Message << "Expected value"
986             << (expectPartialResult ?
987                     " in range: [" + de::toString(expectedMin) + ", " + de::toString(expectedMax) + "]" :
988                     ": " + de::toString(expectedCounter))
989             << tcu::TestLog::EndMessage;
990         log << tcu::TestLog::Message << "Result value: " << de::toString(actualCounter) << tcu::TestLog::EndMessage;
991 
992         if (expectedMin <= actualCounter && actualCounter <= expectedMax)
993             return tcu::TestStatus::pass("Success");
994         else
995             return tcu::TestStatus::fail("Value out of range");
996     }
997 }
998 
999 class EarlyFragmentDiscardTest : public EarlyFragmentTest
1000 {
1001 public:
1002     EarlyFragmentDiscardTest(tcu::TestContext &testCtx, const std::string name, const uint32_t flags);
1003 
1004     void initPrograms(SourceCollections &programCollection) const;
1005     TestInstance *createInstance(Context &context) const;
1006 
1007 private:
1008     const uint32_t m_flags;
1009 };
1010 
EarlyFragmentDiscardTest(tcu::TestContext & testCtx,const std::string name,const uint32_t flags)1011 EarlyFragmentDiscardTest::EarlyFragmentDiscardTest(tcu::TestContext &testCtx, const std::string name,
1012                                                    const uint32_t flags)
1013     : EarlyFragmentTest(testCtx, name, flags)
1014     , m_flags(flags)
1015 {
1016 }
1017 
createInstance(Context & context) const1018 TestInstance *EarlyFragmentDiscardTest::createInstance(Context &context) const
1019 {
1020     return new EarlyFragmentDiscardTestInstance(context, m_flags);
1021 }
1022 
initPrograms(SourceCollections & programCollection) const1023 void EarlyFragmentDiscardTest::initPrograms(SourceCollections &programCollection) const
1024 {
1025     // Vertex
1026     {
1027         std::ostringstream src;
1028         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
1029             << "\n"
1030             << "layout(location = 0) in highp vec4 position;\n"
1031             << "\n"
1032             << "out gl_PerVertex {\n"
1033             << "   vec4 gl_Position;\n"
1034             << "};\n"
1035             << "\n"
1036             << "void main (void)\n"
1037             << "{\n"
1038             << "    gl_Position = position;\n"
1039             << "}\n";
1040 
1041         programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
1042     }
1043 
1044     // Fragment
1045     {
1046         if ((m_flags & FLAG_EARLY_AND_LATE_FRAGMENT_TESTS) == 0)
1047         {
1048             const bool useEarlyTests = (m_flags & FLAG_DONT_USE_EARLY_FRAGMENT_TESTS) == 0;
1049             std::ostringstream src;
1050             src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
1051                 << "\n"
1052                 << (useEarlyTests ? "layout(early_fragment_tests) in;\n" : "")
1053                 << "layout(location = 0) out highp vec4 fragColor;\n"
1054                 << "\n"
1055                 << "layout(binding = 0) coherent buffer Output {\n"
1056                 << "    uint result;\n"
1057                 << "} sb_out;\n"
1058                 << "\n"
1059                 << "void main (void)\n"
1060                 << "{\n"
1061                 << "    atomicAdd(sb_out.result, 1u);\n"
1062                 << "    gl_FragDepth = 0.75f;\n"
1063                 << "    fragColor = vec4(1.0, 1.0, 0.0, 1.0);\n"
1064                 << "    discard;\n"
1065                 << "}\n";
1066             programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
1067         }
1068         else
1069         {
1070             const SpirVAsmBuildOptions buildOptionsSpr(programCollection.usedVulkanVersion, SPIRV_VERSION_1_3);
1071             const std::string src = "; SPIR - V\n"
1072                                     "; Version: 1.0\n"
1073                                     "; Generator: Khronos Glslang Reference Front End; 10\n"
1074                                     "; Bound: 28\n"
1075                                     "; Schema: 0\n"
1076                                     "OpCapability Shader\n"
1077                                     "OpExtension \"SPV_AMD_shader_early_and_late_fragment_tests\"\n"
1078                                     "%1 = OpExtInstImport \"GLSL.std.450\"\n"
1079                                     "OpMemoryModel Logical GLSL450\n"
1080                                     "OpEntryPoint Fragment %4 \"main\" %19 %23\n"
1081                                     "OpExecutionMode %4 OriginUpperLeft\n"
1082                                     "OpExecutionMode %4 EarlyAndLateFragmentTestsAMD\n"
1083                                     "OpExecutionMode %4 DepthReplacing\n"
1084                                     "OpExecutionMode %4 DepthGreater\n"
1085                                     "OpMemberDecorate %7 0 Coherent\n"
1086                                     "OpMemberDecorate %7 0 Offset 0\n"
1087                                     "OpDecorate %7 BufferBlock\n"
1088                                     "OpDecorate %9 DescriptorSet 0\n"
1089                                     "OpDecorate %9 Binding 0\n"
1090                                     "OpDecorate %19 BuiltIn FragDepth\n"
1091                                     "OpDecorate %23 Location 0\n"
1092                                     "%2 = OpTypeVoid\n"
1093                                     "%3 = OpTypeFunction %2\n"
1094                                     "%6 = OpTypeInt 32 0\n"
1095                                     "%7 = OpTypeStruct %6\n"
1096                                     "%8 = OpTypePointer Uniform %7\n"
1097                                     "%9 = OpVariable %8 Uniform\n"
1098                                     "%10 = OpTypeInt 32 1\n"
1099                                     "%11 = OpConstant %10 0\n"
1100                                     "%12 = OpTypePointer Uniform %6\n"
1101                                     "%14 = OpConstant %6 1\n"
1102                                     "%15 = OpConstant %6 0\n"
1103                                     "%17 = OpTypeFloat 32\n"
1104                                     "%18 = OpTypePointer Output %17\n"
1105                                     "%19 = OpVariable %18 Output\n"
1106                                     "%20 = OpConstant %17 0.75\n"
1107                                     "%21 = OpTypeVector %17 4\n"
1108                                     "%22 = OpTypePointer Output %21\n"
1109                                     "%23 = OpVariable %22 Output\n"
1110                                     "%24 = OpConstant %17 1\n"
1111                                     "%25 = OpConstant %17 0\n"
1112                                     "%26 = OpConstantComposite %21 %24 %24 %25 %24\n"
1113                                     "%4 = OpFunction %2 None %3\n"
1114                                     "%5 = OpLabel\n"
1115                                     "%13 = OpAccessChain %12 %9 %11\n"
1116                                     "%16 = OpAtomicIAdd %6 %13 %14 %15 %14\n"
1117                                     "OpStore %19 %20\n"
1118                                     "OpStore %23 %26\n"
1119                                     "OpKill\n"
1120                                     "OpFunctionEnd\n";
1121             programCollection.spirvAsmSources.add("frag") << src << buildOptionsSpr;
1122         }
1123     }
1124 }
1125 
1126 class EarlyFragmentSampleMaskTestInstance : public EarlyFragmentTestInstance
1127 {
1128 public:
1129     EarlyFragmentSampleMaskTestInstance(Context &context, const uint32_t flags, const uint32_t sampleCount);
1130 
1131     tcu::TestStatus iterate(void);
1132 
1133 private:
1134     tcu::TextureLevel generateReferenceColorImage(const tcu::TextureFormat format, const tcu::IVec2 &renderSize);
1135     Move<VkRenderPass> makeRenderPass(const DeviceInterface &vk, const VkDevice device, const VkFormat colorFormat,
1136                                       const VkFormat depthStencilFormat);
1137     Move<VkPipeline> makeGraphicsPipeline(const DeviceInterface &vk, const VkDevice device,
1138                                           const VkPipelineLayout pipelineLayout, const VkRenderPass renderPass,
1139                                           const VkShaderModule vertexModule, const VkShaderModule fragmentModule,
1140                                           const tcu::IVec2 &renderSize, const bool enableDepthTest,
1141                                           const bool enableStencilTest, const VkStencilOp stencilFailOp,
1142                                           const VkStencilOp stencilPassOp);
1143     enum TestMode
1144     {
1145         MODE_INVALID,
1146         MODE_DEPTH,
1147         MODE_STENCIL,
1148     };
1149 
1150     const TestMode m_testMode;
1151     const bool m_useTestAttachment;
1152     const bool m_useEarlyTests;
1153     const uint32_t m_sampleCount;
1154 };
1155 
EarlyFragmentSampleMaskTestInstance(Context & context,const uint32_t flags,const uint32_t sampleCount)1156 EarlyFragmentSampleMaskTestInstance::EarlyFragmentSampleMaskTestInstance(Context &context, const uint32_t flags,
1157                                                                          const uint32_t sampleCount)
1158     : EarlyFragmentTestInstance(context, flags)
1159     , m_testMode(flags & FLAG_TEST_DEPTH   ? MODE_DEPTH :
1160                  flags & FLAG_TEST_STENCIL ? MODE_STENCIL :
1161                                              MODE_INVALID)
1162     , m_useTestAttachment((flags & FLAG_DONT_USE_TEST_ATTACHMENT) == 0)
1163     , m_useEarlyTests((flags & FLAG_DONT_USE_EARLY_FRAGMENT_TESTS) == 0)
1164     , m_sampleCount(sampleCount)
1165 {
1166     DE_ASSERT(m_testMode != MODE_INVALID);
1167 }
1168 
generateReferenceColorImage(const tcu::TextureFormat format,const tcu::IVec2 & renderSize)1169 tcu::TextureLevel EarlyFragmentSampleMaskTestInstance::generateReferenceColorImage(const tcu::TextureFormat format,
1170                                                                                    const tcu::IVec2 &renderSize)
1171 {
1172     tcu::TextureLevel image(format, renderSize.x(), renderSize.y());
1173     const tcu::Vec4 clearColor = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
1174 
1175     tcu::clear(image.getAccess(), clearColor);
1176 
1177     return image;
1178 }
1179 
makeGraphicsPipeline(const DeviceInterface & vk,const VkDevice device,const VkPipelineLayout pipelineLayout,const VkRenderPass renderPass,const VkShaderModule vertexModule,const VkShaderModule fragmentModule,const tcu::IVec2 & renderSize,const bool enableDepthTest,const bool enableStencilTest,const VkStencilOp stencilFailOp,const VkStencilOp stencilPassOp)1180 Move<VkPipeline> EarlyFragmentSampleMaskTestInstance::makeGraphicsPipeline(
1181     const DeviceInterface &vk, const VkDevice device, const VkPipelineLayout pipelineLayout,
1182     const VkRenderPass renderPass, const VkShaderModule vertexModule, const VkShaderModule fragmentModule,
1183     const tcu::IVec2 &renderSize, const bool enableDepthTest, const bool enableStencilTest,
1184     const VkStencilOp stencilFailOp, const VkStencilOp stencilPassOp)
1185 {
1186     const std::vector<VkViewport> viewports(1, makeViewport(renderSize));
1187     const std::vector<VkRect2D> scissors(1, makeRect2D(renderSize));
1188 
1189     const VkStencilOpState stencilOpState = makeStencilOpState(stencilFailOp,       // stencil fail
1190                                                                stencilPassOp,       // depth & stencil pass
1191                                                                VK_STENCIL_OP_KEEP,  // depth only fail
1192                                                                VK_COMPARE_OP_EQUAL, // compare op
1193                                                                0x3,                 // compare mask
1194                                                                0xf,                 // write mask
1195                                                                1u);                 // reference
1196 
1197     const VkPipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo = {
1198         VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType                          sType
1199         DE_NULL,                                                    // const void*                              pNext
1200         0u,                                                         // VkPipelineDepthStencilStateCreateFlags   flags
1201         enableDepthTest ? VK_TRUE : VK_FALSE,   // VkBool32                                 depthTestEnable
1202         enableDepthTest ? VK_TRUE : VK_FALSE,   // VkBool32                                 depthWriteEnable
1203         VK_COMPARE_OP_LESS,                     // VkCompareOp                              depthCompareOp
1204         VK_FALSE,                               // VkBool32                                 depthBoundsTestEnable
1205         enableStencilTest ? VK_TRUE : VK_FALSE, // VkBool32                                 stencilTestEnable
1206         stencilOpState,                         // VkStencilOpState                         front
1207         stencilOpState,                         // VkStencilOpState                         back
1208         0.0f,                                   // float                                    minDepthBounds
1209         1.0f                                    // float                                    maxDepthBounds
1210     };
1211 
1212     // Only allow coverage on sample 0.
1213     const VkSampleMask sampleMask = 0x1;
1214 
1215     const VkPipelineMultisampleStateCreateInfo multisampleStateCreateInfo = {
1216         VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType                            sType
1217         DE_NULL,                                                  // const void*                                pNext
1218         0u,                                                       // VkPipelineMultisampleStateCreateFlags    flags
1219         (VkSampleCountFlagBits)m_sampleCount, // VkSampleCountFlagBits                    rasterizationSamples
1220         true,                                 // VkBool32                                    sampleShadingEnable
1221         0.0f,                                 // float                                    minSampleShading
1222         &sampleMask,                          // const VkSampleMask*                        pSampleMask
1223         false,                                // VkBool32                                    alphaToCoverageEnable
1224         false,                                // VkBool32                                    alphaToOneEnable
1225     };
1226 
1227     return vk::makeGraphicsPipeline(
1228         vk,                                  // const DeviceInterface&                        vk
1229         device,                              // const VkDevice                                device
1230         pipelineLayout,                      // const VkPipelineLayout                        pipelineLayout
1231         vertexModule,                        // const VkShaderModule                          vertexShaderModule
1232         DE_NULL,                             // const VkShaderModule                          tessellationControlModule
1233         DE_NULL,                             // const VkShaderModule                          tessellationEvalModule
1234         DE_NULL,                             // const VkShaderModule                          geometryShaderModule
1235         fragmentModule,                      // const VkShaderModule                          fragmentShaderModule
1236         renderPass,                          // const VkRenderPass                            renderPass
1237         viewports,                           // const std::vector<VkViewport>&                viewports
1238         scissors,                            // const std::vector<VkRect2D>&                  scissors
1239         VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // const VkPrimitiveTopology                     topology
1240         0u,                                  // const uint32_t                                subpass
1241         0u,                                  // const uint32_t                                patchControlPoints
1242         DE_NULL,                             // const VkPipelineVertexInputStateCreateInfo*   vertexInputStateCreateInfo
1243         DE_NULL,                       // const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
1244         &multisampleStateCreateInfo,   // const VkPipelineMultisampleStateCreateInfo*   multisampleStateCreateInfo
1245         &depthStencilStateCreateInfo); // const VkPipelineDepthStencilStateCreateInfo*  depthStencilStateCreateInfo
1246 }
1247 
makeRenderPass(const DeviceInterface & vk,const VkDevice device,const VkFormat colorFormat,const VkFormat depthStencilFormat)1248 Move<VkRenderPass> EarlyFragmentSampleMaskTestInstance::makeRenderPass(const DeviceInterface &vk, const VkDevice device,
1249                                                                        const VkFormat colorFormat,
1250                                                                        const VkFormat depthStencilFormat)
1251 {
1252     const bool hasColor        = colorFormat != VK_FORMAT_UNDEFINED;
1253     const bool hasDepthStencil = depthStencilFormat != VK_FORMAT_UNDEFINED;
1254 
1255     const VkAttachmentDescription2 colorAttachmentDescription = {
1256         VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2, // VkStructureType sType;
1257         DE_NULL,                                    // const void* pNext;
1258         (VkAttachmentDescriptionFlags)0,            // VkAttachmentDescriptionFlags    flags
1259         colorFormat,                                // VkFormat                        format
1260         (VkSampleCountFlagBits)m_sampleCount,       // VkSampleCountFlagBits           samples
1261         VK_ATTACHMENT_LOAD_OP_CLEAR,                // VkAttachmentLoadOp              loadOp
1262         VK_ATTACHMENT_STORE_OP_STORE,               // VkAttachmentStoreOp             storeOp
1263         VK_ATTACHMENT_LOAD_OP_DONT_CARE,            // VkAttachmentLoadOp              stencilLoadOp
1264         VK_ATTACHMENT_STORE_OP_DONT_CARE,           // VkAttachmentStoreOp             stencilStoreOp
1265         VK_IMAGE_LAYOUT_UNDEFINED,                  // VkImageLayout                   initialLayout
1266         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL    // VkImageLayout                   finalLayout
1267     };
1268 
1269     const VkAttachmentDescription2 depthStencilAttachmentDescription = {
1270         VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2,       // VkStructureType sType;
1271         DE_NULL,                                          // const void* pNext;
1272         (VkAttachmentDescriptionFlags)0,                  // VkAttachmentDescriptionFlags    flags
1273         depthStencilFormat,                               // VkFormat                        format
1274         (VkSampleCountFlagBits)m_sampleCount,             // VkSampleCountFlagBits           samples
1275         VK_ATTACHMENT_LOAD_OP_CLEAR,                      // VkAttachmentLoadOp              loadOp
1276         VK_ATTACHMENT_STORE_OP_STORE,                     // VkAttachmentStoreOp             storeOp
1277         VK_ATTACHMENT_LOAD_OP_CLEAR,                      // VkAttachmentLoadOp              stencilLoadOp
1278         VK_ATTACHMENT_STORE_OP_STORE,                     // VkAttachmentStoreOp             stencilStoreOp
1279         VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout                   initialLayout
1280         VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL  // VkImageLayout                   finalLayout
1281     };
1282 
1283     const VkAttachmentDescription2 resolveAttachmentDescription = {
1284         VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2, // VkStructureType sType;
1285         DE_NULL,                                    // const void* pNext;
1286         (VkAttachmentDescriptionFlags)0,            // VkAttachmentDescriptionFlags    flags
1287         colorFormat,                                // VkFormat                        format
1288         VK_SAMPLE_COUNT_1_BIT,                      // VkSampleCountFlagBits           samples
1289         VK_ATTACHMENT_LOAD_OP_CLEAR,                // VkAttachmentLoadOp              loadOp
1290         VK_ATTACHMENT_STORE_OP_STORE,               // VkAttachmentStoreOp             storeOp
1291         VK_ATTACHMENT_LOAD_OP_DONT_CARE,            // VkAttachmentLoadOp              stencilLoadOp
1292         VK_ATTACHMENT_STORE_OP_DONT_CARE,           // VkAttachmentStoreOp             stencilStoreOp
1293         VK_IMAGE_LAYOUT_UNDEFINED,                  // VkImageLayout                   initialLayout
1294         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL    // VkImageLayout                   finalLayout
1295     };
1296 
1297     const VkAttachmentDescription2 resolveDepthStencilAttachmentDescription = {
1298         VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2,       // VkStructureType sType;
1299         DE_NULL,                                          // const void* pNext;
1300         (VkAttachmentDescriptionFlags)0,                  // VkAttachmentDescriptionFlags    flags
1301         depthStencilFormat,                               // VkFormat                        format
1302         VK_SAMPLE_COUNT_1_BIT,                            // VkSampleCountFlagBits           samples
1303         VK_ATTACHMENT_LOAD_OP_CLEAR,                      // VkAttachmentLoadOp              loadOp
1304         VK_ATTACHMENT_STORE_OP_STORE,                     // VkAttachmentStoreOp             storeOp
1305         VK_ATTACHMENT_LOAD_OP_CLEAR,                      // VkAttachmentLoadOp              stencilLoadOp
1306         VK_ATTACHMENT_STORE_OP_STORE,                     // VkAttachmentStoreOp             stencilStoreOp
1307         VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout                   initialLayout
1308         VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL  // VkImageLayout                   finalLayout
1309     };
1310 
1311     std::vector<VkAttachmentDescription2> attachmentDescriptions;
1312 
1313     if (hasColor)
1314         attachmentDescriptions.push_back(colorAttachmentDescription);
1315     if (hasDepthStencil)
1316         attachmentDescriptions.push_back(depthStencilAttachmentDescription);
1317     if (hasColor)
1318         attachmentDescriptions.push_back(resolveAttachmentDescription);
1319     if (hasDepthStencil)
1320         attachmentDescriptions.push_back(resolveDepthStencilAttachmentDescription);
1321 
1322     const VkAttachmentReference2 colorAttachmentRef = {
1323         VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, // VkStructureType sType;
1324         DE_NULL,                                  // const void* pNext;
1325         0u,                                       // uint32_t                attachment
1326         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout        layout
1327         VK_IMAGE_ASPECT_COLOR_BIT                 // VkImageAspectFlags aspectMask;
1328     };
1329 
1330     const VkAttachmentReference2 depthStencilAttachmentRef = {
1331         VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2,         // VkStructureType sType;
1332         DE_NULL,                                          // const void* pNext;
1333         hasDepthStencil ? 1u : 0u,                        // uint32_t                attachment
1334         VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout        layout
1335         VkImageAspectFlags(m_testMode == MODE_DEPTH ? VK_IMAGE_ASPECT_DEPTH_BIT :
1336                                                       VK_IMAGE_ASPECT_STENCIL_BIT) // VkImageAspectFlags aspectMask;
1337     };
1338 
1339     const VkAttachmentReference2 resolveAttachmentRef = {
1340         VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, // VkStructureType sType;
1341         DE_NULL,                                  // const void* pNext;
1342         hasColor ? 2u : 0u,                       // uint32_t                attachment
1343         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout        layout
1344         VK_IMAGE_ASPECT_COLOR_BIT                 // VkImageAspectFlags aspectMask;
1345     };
1346 
1347     const VkAttachmentReference2 depthStencilResolveAttachmentRef = {
1348         VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2,         // VkStructureType sType;
1349         DE_NULL,                                          // const void* pNext;
1350         hasDepthStencil ? 3u : 0u,                        // uint32_t                attachment
1351         VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout        layout
1352         VkImageAspectFlags(m_testMode == MODE_DEPTH ? VK_IMAGE_ASPECT_DEPTH_BIT :
1353                                                       VK_IMAGE_ASPECT_STENCIL_BIT) // VkImageAspectFlags aspectMask;
1354     };
1355 
1356     // Using VK_RESOLVE_MODE_SAMPLE_ZERO_BIT as resolve mode, so no need to check its support as it is mandatory in the extension.
1357     const VkSubpassDescriptionDepthStencilResolve depthStencilResolveDescription = {
1358         VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE, // VkStructureType sType;
1359         DE_NULL,                                                     // const void* pNext;
1360         VK_RESOLVE_MODE_SAMPLE_ZERO_BIT,                             // VkResolveModeFlagBits depthResolveMode;
1361         VK_RESOLVE_MODE_SAMPLE_ZERO_BIT,                             // VkResolveModeFlagBits stencilResolveMode;
1362         &depthStencilResolveAttachmentRef // const VkAttachmentReference2* pDepthStencilResolveAttachment;
1363     };
1364 
1365     const VkSubpassDescription2 subpassDescription = {
1366         VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2,                     // VkStructureType sType;
1367         hasDepthStencil ? &depthStencilResolveDescription : DE_NULL, // const void* pNext;
1368         (VkSubpassDescriptionFlags)0,                                // VkSubpassDescriptionFlags        flags
1369         VK_PIPELINE_BIND_POINT_GRAPHICS,            // VkPipelineBindPoint                pipelineBindPoint
1370         0u,                                         // uint32_t viewMask;
1371         0u,                                         // uint32_t                            inputAttachmentCount
1372         DE_NULL,                                    // const VkAttachmentReference2*    pInputAttachments
1373         hasColor ? 1u : 0u,                         // uint32_t                            colorAttachmentCount
1374         hasColor ? &colorAttachmentRef : DE_NULL,   // const VkAttachmentReference2*    pColorAttachments
1375         hasColor ? &resolveAttachmentRef : DE_NULL, // const VkAttachmentReference2*    pResolveAttachments
1376         hasDepthStencil ? &depthStencilAttachmentRef :
1377                           DE_NULL, // const VkAttachmentReference2*    pDepthStencilAttachment
1378         0u,                        // uint32_t                            preserveAttachmentCount
1379         DE_NULL                    // const uint32_t*                    pPreserveAttachments
1380     };
1381 
1382     const VkRenderPassCreateInfo2 renderPassInfo = {
1383         VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2, // VkStructureType                   sType
1384         DE_NULL,                                     // const void*                       pNext
1385         (VkRenderPassCreateFlags)0,                  // VkRenderPassCreateFlags           flags
1386         (uint32_t)attachmentDescriptions.size(),     // uint32_t                          attachmentCount
1387         attachmentDescriptions.size() > 0 ? &attachmentDescriptions[0] :
1388                                             DE_NULL, // const VkAttachmentDescription2*    pAttachments
1389         1u,                                          // uint32_t                          subpassCount
1390         &subpassDescription,                         // const VkSubpassDescription2*       pSubpasses
1391         0u,                                          // uint32_t                          dependencyCount
1392         DE_NULL,                                     // const VkSubpassDependency*        pDependencies
1393         0u,                                          // uint32_t correlatedViewMaskCount;
1394         DE_NULL,                                     // const uint32_t* pCorrelatedViewMasks;
1395     };
1396 
1397     return createRenderPass2(vk, device, &renderPassInfo, DE_NULL);
1398 }
1399 
iterate(void)1400 tcu::TestStatus EarlyFragmentSampleMaskTestInstance::iterate(void)
1401 {
1402     const DeviceInterface &vk         = m_context.getDeviceInterface();
1403     const InstanceInterface &vki      = m_context.getInstanceInterface();
1404     const VkDevice device             = m_context.getDevice();
1405     const VkPhysicalDevice physDevice = m_context.getPhysicalDevice();
1406     const VkQueue queue               = m_context.getUniversalQueue();
1407     const uint32_t queueFamilyIndex   = m_context.getUniversalQueueFamilyIndex();
1408     Allocator &allocator              = m_context.getDefaultAllocator();
1409     const VkFormat colorFormat        = VK_FORMAT_R8G8B8A8_UNORM;
1410 
1411     DE_ASSERT(m_useTestAttachment);
1412     DE_UNREF(m_useTestAttachment);
1413 
1414     // Test attachment (depth or stencil)
1415     static const VkFormat stencilFormats[] = {
1416         // One of the following formats must be supported, as per spec requirement.
1417         VK_FORMAT_S8_UINT,
1418         VK_FORMAT_D16_UNORM_S8_UINT,
1419         VK_FORMAT_D24_UNORM_S8_UINT,
1420         VK_FORMAT_D32_SFLOAT_S8_UINT,
1421     };
1422 
1423     const VkFormat depthStencilFormat =
1424         (m_testMode == MODE_STENCIL ?
1425              pickSupportedDepthStencilFormat(vki, physDevice, DE_LENGTH_OF_ARRAY(stencilFormats), stencilFormats) :
1426              VK_FORMAT_D16_UNORM); // spec requires this format to be supported
1427 
1428     if (depthStencilFormat == VK_FORMAT_UNDEFINED)
1429         return tcu::TestStatus::fail("Required depth/stencil format not supported");
1430 
1431     m_context.getTestContext().getLog() << tcu::TestLog::Message << "Using depth/stencil format "
1432                                         << getFormatName(depthStencilFormat) << tcu::TestLog::EndMessage;
1433 
1434     // Check support for MSAA image formats used in the test.
1435     VkImageFormatProperties formatProperties;
1436     vki.getPhysicalDeviceImageFormatProperties(physDevice, colorFormat, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
1437                                                VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
1438                                                0u, &formatProperties);
1439     if ((formatProperties.sampleCounts & m_sampleCount) == 0)
1440         TCU_THROW(NotSupportedError, "Format does not support this number of samples for color format");
1441 
1442     vki.getPhysicalDeviceImageFormatProperties(
1443         physDevice, depthStencilFormat, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
1444         VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 0u, &formatProperties);
1445     if ((formatProperties.sampleCounts & m_sampleCount) == 0)
1446         TCU_THROW(NotSupportedError, "Format does not support this number of samples for depth-stencil format");
1447 
1448     // Color attachment
1449     const tcu::IVec2 renderSize = tcu::IVec2(32, 32);
1450     const VkImageSubresourceRange colorSubresourceRange =
1451         makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
1452 
1453     const VkImageCreateInfo imageParams = {
1454         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                                   // VkStructureType sType;
1455         DE_NULL,                                                               // const void* pNext;
1456         (VkImageCreateFlags)0,                                                 // VkImageCreateFlags flags;
1457         VK_IMAGE_TYPE_2D,                                                      // VkImageType imageType;
1458         colorFormat,                                                           // VkFormat format;
1459         makeExtent3D(renderSize.x(), renderSize.y(), 1),                       // VkExtent3D extent;
1460         1u,                                                                    // uint32_t mipLevels;
1461         1u,                                                                    // uint32_t arrayLayers;
1462         (VkSampleCountFlagBits)m_sampleCount,                                  // VkSampleCountFlagBits samples;
1463         VK_IMAGE_TILING_OPTIMAL,                                               // VkImageTiling tiling;
1464         VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage;
1465         VK_SHARING_MODE_EXCLUSIVE,                                             // VkSharingMode sharingMode;
1466         0u,                                                                    // uint32_t queueFamilyIndexCount;
1467         DE_NULL,                                                               // const uint32_t* pQueueFamilyIndices;
1468         VK_IMAGE_LAYOUT_UNDEFINED,                                             // VkImageLayout initialLayout;
1469     };
1470     const Unique<VkImage> colorImage(makeImage(vk, device, imageParams));
1471     const UniquePtr<Allocation> colorImageAlloc(bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any));
1472     const Unique<VkImageView> colorImageView(
1473         makeImageView(vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange));
1474 
1475     const Unique<VkImage> resolveColorImage(
1476         makeImage(vk, device,
1477                   makeImageCreateInfo(renderSize, colorFormat,
1478                                       VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
1479     const UniquePtr<Allocation> resolveColorImageAlloc(
1480         bindImage(vk, device, allocator, *resolveColorImage, MemoryRequirement::Any));
1481     const Unique<VkImageView> resolveColorImageView(
1482         makeImageView(vk, device, *resolveColorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange));
1483 
1484     // Depth-Stencil attachment
1485     const VkImageSubresourceRange depthStencilSubresourceRange =
1486         makeImageSubresourceRange(getImageAspectFlags(depthStencilFormat), 0u, 1u, 0u, 1u);
1487 
1488     const VkImageCreateInfo depthStencilImageParams = {
1489         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                                           // VkStructureType sType;
1490         DE_NULL,                                                                       // const void* pNext;
1491         (VkImageCreateFlags)0,                                                         // VkImageCreateFlags flags;
1492         VK_IMAGE_TYPE_2D,                                                              // VkImageType imageType;
1493         depthStencilFormat,                                                            // VkFormat format;
1494         makeExtent3D(renderSize.x(), renderSize.y(), 1),                               // VkExtent3D extent;
1495         1u,                                                                            // uint32_t mipLevels;
1496         1u,                                                                            // uint32_t arrayLayers;
1497         (VkSampleCountFlagBits)m_sampleCount,                                          // VkSampleCountFlagBits samples;
1498         VK_IMAGE_TILING_OPTIMAL,                                                       // VkImageTiling tiling;
1499         VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage;
1500         VK_SHARING_MODE_EXCLUSIVE,                                                     // VkSharingMode sharingMode;
1501         0u,                        // uint32_t queueFamilyIndexCount;
1502         DE_NULL,                   // const uint32_t* pQueueFamilyIndices;
1503         VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
1504     };
1505     const Unique<VkImage> depthStencilImage(makeImage(vk, device, depthStencilImageParams));
1506     const UniquePtr<Allocation> depthStencilImageAlloc(
1507         bindImage(vk, device, allocator, *depthStencilImage, MemoryRequirement::Any));
1508     const Unique<VkImageView> depthStencilImageView(makeImageView(vk, device, *depthStencilImage, VK_IMAGE_VIEW_TYPE_2D,
1509                                                                   depthStencilFormat, depthStencilSubresourceRange));
1510 
1511     const Unique<VkImage> resolveDepthStencilImage(
1512         makeImage(vk, device,
1513                   makeImageCreateInfo(renderSize, depthStencilFormat,
1514                                       VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
1515     const UniquePtr<Allocation> resolveDepthStencilImageAlloc(
1516         bindImage(vk, device, allocator, *resolveDepthStencilImage, MemoryRequirement::Any));
1517     const Unique<VkImageView> resolveDepthStencilImageView(makeImageView(vk, device, *resolveDepthStencilImage,
1518                                                                          VK_IMAGE_VIEW_TYPE_2D, depthStencilFormat,
1519                                                                          depthStencilSubresourceRange));
1520 
1521     const VkImageView attachmentImages[]   = {*colorImageView, *depthStencilImageView, *resolveColorImageView,
1522                                               *resolveDepthStencilImageView};
1523     const uint32_t numUsedAttachmentImages = DE_LENGTH_OF_ARRAY(attachmentImages);
1524 
1525     // Vertex buffer
1526 
1527     const uint32_t numVertices               = 6u;
1528     const VkDeviceSize vertexBufferSizeBytes = sizeof(tcu::Vec4) * numVertices;
1529     const Unique<VkBuffer> vertexBuffer(
1530         makeBuffer(vk, device, vertexBufferSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
1531     const UniquePtr<Allocation> vertexBufferAlloc(
1532         bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible));
1533 
1534     {
1535         tcu::Vec4 *const pVertices = reinterpret_cast<tcu::Vec4 *>(vertexBufferAlloc->getHostPtr());
1536 
1537         pVertices[0] = tcu::Vec4(1.0f, -1.0f, 0.5f, 1.0f);
1538         pVertices[1] = tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f);
1539         pVertices[2] = tcu::Vec4(-1.0f, 1.0f, 0.5f, 1.0f);
1540 
1541         pVertices[3] = tcu::Vec4(-1.0f, 1.0f, 0.5f, 1.0f);
1542         pVertices[4] = tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f);
1543         pVertices[5] = tcu::Vec4(1.0f, -1.0f, 0.5f, 1.0f);
1544 
1545         flushAlloc(vk, device, *vertexBufferAlloc);
1546         // No barrier needed, flushed memory is automatically visible
1547     }
1548 
1549     // Result buffer
1550 
1551     const VkDeviceSize resultBufferSizeBytes = sizeof(uint32_t);
1552     const Unique<VkBuffer> resultBuffer(
1553         makeBuffer(vk, device, resultBufferSizeBytes, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT));
1554     const UniquePtr<Allocation> resultBufferAlloc(
1555         bindBuffer(vk, device, allocator, *resultBuffer, MemoryRequirement::HostVisible));
1556 
1557     {
1558         uint32_t *const pData = static_cast<uint32_t *>(resultBufferAlloc->getHostPtr());
1559 
1560         *pData = 0;
1561         flushAlloc(vk, device, *resultBufferAlloc);
1562     }
1563 
1564     // Render result buffer (to retrieve color attachment contents)
1565 
1566     const VkDeviceSize colorBufferSizeBytes =
1567         tcu::getPixelSize(mapVkFormat(colorFormat)) * renderSize.x() * renderSize.y();
1568     const Unique<VkBuffer> colorBuffer(makeBuffer(vk, device, colorBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1569     const UniquePtr<Allocation> colorBufferAlloc(
1570         bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
1571 
1572     // Depth stencil result buffer (to retrieve depth-stencil attachment contents)
1573 
1574     const VkDeviceSize dsBufferSizeBytes =
1575         tcu::getPixelSize(mapVkFormat(depthStencilFormat)) * renderSize.x() * renderSize.y();
1576     const Unique<VkBuffer> dsBuffer(makeBuffer(vk, device, dsBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1577     const UniquePtr<Allocation> dsBufferAlloc(
1578         bindBuffer(vk, device, allocator, *dsBuffer, MemoryRequirement::HostVisible));
1579 
1580     // Descriptors
1581 
1582     const Unique<VkDescriptorSetLayout> descriptorSetLayout(
1583         DescriptorSetLayoutBuilder()
1584             .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT)
1585             .build(vk, device));
1586 
1587     const Unique<VkDescriptorPool> descriptorPool(
1588         DescriptorPoolBuilder()
1589             .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
1590             .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
1591 
1592     const Unique<VkDescriptorSet> descriptorSet(makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
1593     const VkDescriptorBufferInfo resultBufferDescriptorInfo =
1594         makeDescriptorBufferInfo(resultBuffer.get(), 0ull, resultBufferSizeBytes);
1595 
1596     DescriptorSetUpdateBuilder()
1597         .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
1598                      VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultBufferDescriptorInfo)
1599         .update(vk, device);
1600 
1601     // Pipeline
1602 
1603     const Unique<VkShaderModule> vertexModule(
1604         createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
1605     const Unique<VkShaderModule> fragmentModule(
1606         createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u));
1607 
1608     const Unique<VkRenderPass> renderPass(makeRenderPass(vk, device, colorFormat, depthStencilFormat));
1609     const Unique<VkFramebuffer> framebuffer(makeFramebuffer(vk, device, *renderPass, numUsedAttachmentImages,
1610                                                             attachmentImages, renderSize.x(), renderSize.y()));
1611     const Unique<VkPipelineLayout> pipelineLayout(makePipelineLayout(vk, device, *descriptorSetLayout));
1612     const Unique<VkPipeline> pipeline(
1613         makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule, renderSize,
1614                              (m_testMode == MODE_DEPTH), (m_testMode == MODE_STENCIL),
1615                              VK_STENCIL_OP_INCREMENT_AND_CLAMP, VK_STENCIL_OP_INCREMENT_AND_CLAMP));
1616     const Unique<VkCommandPool> cmdPool(
1617         createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1618     const Unique<VkCommandBuffer> cmdBuffer(
1619         allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1620 
1621     // Draw commands
1622 
1623     {
1624         const VkRect2D renderArea = {
1625             makeOffset2D(0, 0),
1626             makeExtent2D(renderSize.x(), renderSize.y()),
1627         };
1628         const tcu::Vec4 clearColor(0.0f, 0.0f, 0.0f, 1.0f);
1629         const VkDeviceSize vertexBufferOffset = 0ull;
1630 
1631         beginCommandBuffer(vk, *cmdBuffer);
1632 
1633         {
1634             const VkImageMemoryBarrier barriers[] = {
1635                 makeImageMemoryBarrier(0u, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
1636                                        VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, *colorImage, colorSubresourceRange),
1637                 makeImageMemoryBarrier(0u, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
1638                                        VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, *depthStencilImage,
1639                                        depthStencilSubresourceRange),
1640                 makeImageMemoryBarrier(0u, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
1641                                        VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, *resolveColorImage,
1642                                        colorSubresourceRange),
1643                 makeImageMemoryBarrier(0u, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
1644                                        VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, *resolveDepthStencilImage,
1645                                        depthStencilSubresourceRange),
1646             };
1647 
1648             vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT,
1649                                   VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
1650                                       VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
1651                                   0u, 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
1652         }
1653 
1654         // Will clear the attachments with specified depth and stencil values.
1655         {
1656             const VkClearValue clearValues[] = {
1657                 makeClearValueColor(clearColor),      // attachment 0
1658                 makeClearValueDepthStencil(0.5f, 3u), // attachment 1
1659                 makeClearValueColor(clearColor),      // attachment 2
1660                 makeClearValueDepthStencil(0.5f, 3u), // attachment 3
1661             };
1662 
1663             const VkRenderPassBeginInfo renderPassBeginInfo = {
1664                 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType         sType;
1665                 DE_NULL,                                  // const void*             pNext;
1666                 *renderPass,                              // VkRenderPass            renderPass;
1667                 *framebuffer,                             // VkFramebuffer           framebuffer;
1668                 renderArea,                               // VkRect2D                renderArea;
1669                 DE_LENGTH_OF_ARRAY(clearValues),          // uint32_t                clearValueCount;
1670                 clearValues,                              // const VkClearValue*     pClearValues;
1671             };
1672 
1673             vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
1674         }
1675 
1676         vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1677         vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u,
1678                                  &descriptorSet.get(), 0u, DE_NULL);
1679         vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
1680 
1681         // Mask half of the attachment image with value that will pass the stencil test.
1682         if (m_testMode == MODE_STENCIL)
1683             commandClearStencilAttachment(vk, *cmdBuffer, makeOffset2D(0, 0),
1684                                           makeExtent2D(renderSize.x() / 2, renderSize.y()), 1u);
1685 
1686         vk.cmdDraw(*cmdBuffer, numVertices, 1u, 0u, 0u);
1687         endRenderPass(vk, *cmdBuffer);
1688 
1689         copyImageToBuffer(vk, *cmdBuffer, *resolveColorImage, *colorBuffer, renderSize,
1690                           VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
1691         VkImageAspectFlags dsAspect =
1692             m_testMode == MODE_DEPTH ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_STENCIL_BIT;
1693         copyImageToBuffer(vk, *cmdBuffer, *resolveDepthStencilImage, *dsBuffer, renderSize,
1694                           VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
1695                           VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, 1u, dsAspect, dsAspect);
1696 
1697         endCommandBuffer(vk, *cmdBuffer);
1698         submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1699     }
1700 
1701     // Verify color output
1702     {
1703         invalidateAlloc(vk, device, *colorBufferAlloc);
1704 
1705         const tcu::ConstPixelBufferAccess imagePixelAccess(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1,
1706                                                            colorBufferAlloc->getHostPtr());
1707         const tcu::TextureLevel referenceImage = generateReferenceColorImage(mapVkFormat(colorFormat), renderSize);
1708         if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison",
1709                                         referenceImage.getAccess(), imagePixelAccess, tcu::Vec4(0.02f),
1710                                         tcu::COMPARE_LOG_RESULT))
1711             printf("Rendered color image is not correct");
1712     }
1713 
1714     // Verify depth-stencil output
1715     {
1716         invalidateAlloc(vk, device, *dsBufferAlloc);
1717         tcu::TextureFormat format = mapVkFormat(depthStencilFormat);
1718         const tcu::ConstPixelBufferAccess dsPixelAccess(format, renderSize.x(), renderSize.y(), 1,
1719                                                         dsBufferAlloc->getHostPtr());
1720 
1721         for (int z = 0; z < dsPixelAccess.getDepth(); z++)
1722             for (int y = 0; y < dsPixelAccess.getHeight(); y++)
1723                 for (int x = 0; x < dsPixelAccess.getWidth(); x++)
1724                 {
1725                     float depthValue = (m_testMode == MODE_DEPTH) ? dsPixelAccess.getPixDepth(x, y, z) : 0.0f;
1726                     int stencilValue = (m_testMode == MODE_STENCIL) ? dsPixelAccess.getPixStencil(x, y, z) : 0;
1727 
1728                     // Depth test should write to the depth buffer even when there is a discard in the fragment shader,
1729                     // when early fragment tests are enabled.
1730                     if (m_testMode == MODE_DEPTH)
1731                     {
1732                         if (m_useEarlyTests && ((x + y) < 31) && depthValue >= 0.5f)
1733                         {
1734                             std::ostringstream error;
1735                             error << "Rendered depth value [ " << x << ", " << y << ", " << z
1736                                   << "] is not correct: " << depthValue << " >= 0.5f";
1737                             TCU_FAIL(error.str().c_str());
1738                         }
1739                         // When early fragment tests are disabled, the depth test happens after the fragment shader, but as we are discarding
1740                         // all fragments, the stored value in the depth buffer should be the clear one (0.5f).
1741                         if (!m_useEarlyTests && deAbs(depthValue - 0.5f) > 0.01f)
1742                         {
1743                             std::ostringstream error;
1744                             error << "Rendered depth value [ " << x << ", " << y << ", " << z
1745                                   << "] is not correct: " << depthValue << " != 0.5f";
1746                             TCU_FAIL(error.str().c_str());
1747                         }
1748                     }
1749 
1750                     if (m_testMode == MODE_STENCIL)
1751                     {
1752                         if (m_useEarlyTests && ((x < 16 && stencilValue != 2u) || (x >= 16 && stencilValue != 4u)))
1753                         {
1754                             std::ostringstream error;
1755                             error << "Rendered stencil value [ " << x << ", " << y << ", " << z
1756                                   << "] is not correct: " << stencilValue << " != ";
1757                             error << (x < 16 ? 2u : 4u);
1758                             TCU_FAIL(error.str().c_str());
1759                         }
1760 
1761                         if (!m_useEarlyTests && ((x < 16 && stencilValue != 1u) || (x >= 16 && stencilValue != 3u)))
1762                         {
1763                             std::ostringstream error;
1764                             error << "Rendered stencil value [ " << x << ", " << y << ", " << z
1765                                   << "] is not correct: " << stencilValue << " != ";
1766                             error << (x < 16 ? 1u : 3u);
1767                             TCU_FAIL(error.str().c_str());
1768                         }
1769                     }
1770                 }
1771     }
1772 
1773     // Verify we process all the fragments
1774     {
1775         invalidateAlloc(vk, device, *resultBufferAlloc);
1776 
1777         const int actualCounter        = *static_cast<int32_t *>(resultBufferAlloc->getHostPtr());
1778         const bool expectPartialResult = m_useEarlyTests;
1779         const int expectedCounter =
1780             expectPartialResult ? renderSize.x() * renderSize.y() / 2 : renderSize.x() * renderSize.y();
1781         const int tolerance   = expectPartialResult ? de::max(renderSize.x(), renderSize.y()) * 3 : 0;
1782         const int expectedMin = de::max(0, expectedCounter - tolerance);
1783 
1784         tcu::TestLog &log = m_context.getTestContext().getLog();
1785         log << tcu::TestLog::Message << "Minimum expected value: " + de::toString(expectedMin)
1786             << tcu::TestLog::EndMessage;
1787         log << tcu::TestLog::Message << "Result value: " << de::toString(actualCounter) << tcu::TestLog::EndMessage;
1788 
1789         if (expectedMin <= actualCounter)
1790             return tcu::TestStatus::pass("Success");
1791         else
1792             return tcu::TestStatus::fail("Value out of range");
1793     }
1794 }
1795 
1796 class EarlyFragmentSampleMaskTest : public EarlyFragmentTest
1797 {
1798 public:
1799     EarlyFragmentSampleMaskTest(tcu::TestContext &testCtx, const std::string name, const uint32_t flags,
1800                                 const uint32_t sampleCount);
1801 
1802     void initPrograms(SourceCollections &programCollection) const override;
1803     TestInstance *createInstance(Context &context) const override;
1804     void checkSupport(Context &context) const override;
1805 
1806 private:
1807     const uint32_t m_flags;
1808     const uint32_t m_sampleCount;
1809 };
1810 
EarlyFragmentSampleMaskTest(tcu::TestContext & testCtx,const std::string name,const uint32_t flags,const uint32_t sampleCount)1811 EarlyFragmentSampleMaskTest::EarlyFragmentSampleMaskTest(tcu::TestContext &testCtx, const std::string name,
1812                                                          const uint32_t flags, const uint32_t sampleCount)
1813     : EarlyFragmentTest(testCtx, name, flags)
1814     , m_flags(flags)
1815     , m_sampleCount(sampleCount)
1816 {
1817 }
1818 
createInstance(Context & context) const1819 TestInstance *EarlyFragmentSampleMaskTest::createInstance(Context &context) const
1820 {
1821     return new EarlyFragmentSampleMaskTestInstance(context, m_flags, m_sampleCount);
1822 }
1823 
initPrograms(SourceCollections & programCollection) const1824 void EarlyFragmentSampleMaskTest::initPrograms(SourceCollections &programCollection) const
1825 {
1826     // Vertex
1827     {
1828         std::ostringstream src;
1829         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
1830             << "\n"
1831             << "layout(location = 0) in highp vec4 position;\n"
1832             << "\n"
1833             << "out gl_PerVertex {\n"
1834             << "   vec4 gl_Position;\n"
1835             << "};\n"
1836             << "\n"
1837             << "void main (void)\n"
1838             << "{\n"
1839             << "    gl_Position = position;\n"
1840             << "}\n";
1841 
1842         programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
1843     }
1844 
1845     // Fragment
1846     {
1847         if ((m_flags & FLAG_EARLY_AND_LATE_FRAGMENT_TESTS) == 0)
1848         {
1849             const bool useEarlyTests = (m_flags & FLAG_DONT_USE_EARLY_FRAGMENT_TESTS) == 0;
1850             std::ostringstream src;
1851             src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
1852                 << "\n"
1853                 << (useEarlyTests ? "layout(early_fragment_tests) in;\n" : "")
1854                 << "layout(location = 0) out highp vec4 fragColor;\n"
1855                 << "\n"
1856                 << "layout(binding = 0) coherent buffer Output {\n"
1857                 << "    uint result;\n"
1858                 << "} sb_out;\n"
1859                 << "\n"
1860                 << "void main (void)\n"
1861                 << "{\n"
1862                 << "    atomicAdd(sb_out.result, 1u);\n"
1863                 << "    gl_SampleMask[0] = 0x0;\n"
1864                 << "    fragColor = vec4(1.0, 1.0, 0.0, 1.0);\n"
1865                 << "    discard;\n"
1866                 << "}\n";
1867 
1868             programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
1869         }
1870         else
1871         {
1872             const SpirVAsmBuildOptions buildOptionsSpr(programCollection.usedVulkanVersion, SPIRV_VERSION_1_3);
1873             const std::string option = (((m_flags & FLAG_DONT_USE_EARLY_FRAGMENT_TESTS) != 0) ?
1874                                             "OpExecutionMode %4 DepthReplacing\nOpExecutionMode %4 DepthGreater\n" :
1875                                             "");
1876             const std::string src    = "; SPIR - V\n"
1877                                        "; Version: 1.0\n"
1878                                        "; Generator: Khronos Glslang Reference Front End; 10\n"
1879                                        "; Bound: 30\n"
1880                                        "; Schema: 0\n"
1881                                        "OpCapability Shader\n"
1882                                        "OpExtension \"SPV_AMD_shader_early_and_late_fragment_tests\"\n"
1883                                        "%1 = OpExtInstImport \"GLSL.std.450\"\n"
1884                                        "OpMemoryModel Logical GLSL450\n"
1885                                        "OpEntryPoint Fragment %4 \"main\" %19 %25\n"
1886                                        "OpExecutionMode %4 OriginUpperLeft\n"
1887                                        "OpExecutionMode %4 EarlyAndLateFragmentTestsAMD\n" +
1888                                     option +
1889                                     "OpMemberDecorate %7 0 Coherent\n"
1890                                     "OpMemberDecorate %7 0 Offset 0\n"
1891                                     "OpDecorate %7 BufferBlock\n"
1892                                     "OpDecorate %9 DescriptorSet 0\n"
1893                                     "OpDecorate %9 Binding 0\n"
1894                                     "OpDecorate %19 BuiltIn SampleMask\n"
1895                                     "OpDecorate %25 Location 0\n"
1896                                     "%2 = OpTypeVoid\n"
1897                                     "%3 = OpTypeFunction %2\n"
1898                                     "%6 = OpTypeInt 32 0\n"
1899                                     "%7 = OpTypeStruct %6\n"
1900                                     "%8 = OpTypePointer Uniform %7\n"
1901                                     "%9 = OpVariable %8 Uniform\n"
1902                                     "%10 = OpTypeInt 32 1\n"
1903                                     "%11 = OpConstant %10 0\n"
1904                                     "%12 = OpTypePointer Uniform %6\n"
1905                                     "%14 = OpConstant %6 1\n"
1906                                     "%15 = OpConstant %6 0\n"
1907                                     "%17 = OpTypeArray %10 %14\n"
1908                                     "%18 = OpTypePointer Output %17\n"
1909                                     "%19 = OpVariable %18 Output\n"
1910                                     "%20 = OpTypePointer Output %10\n"
1911                                     "%22 = OpTypeFloat 32\n"
1912                                     "%23 = OpTypeVector %22 4\n"
1913                                     "%24 = OpTypePointer Output %23\n"
1914                                     "%25 = OpVariable %24 Output\n"
1915                                     "%26 = OpConstant %22 1\n"
1916                                     "%27 = OpConstant %22 0\n"
1917                                     "%28 = OpConstantComposite %23 %26 %26 %27 %26\n"
1918                                     "%4 = OpFunction %2 None %3\n"
1919                                     "%5 = OpLabel\n"
1920                                     "%13 = OpAccessChain %12 %9 %11\n"
1921                                     "%16 = OpAtomicIAdd %6 %13 %14 %15 %14\n"
1922                                     "%21 = OpAccessChain %20 %19 %11\n"
1923                                     "OpStore %21 %11\n"
1924                                     "OpStore %25 %28\n"
1925                                     "OpKill\n"
1926                                     "OpFunctionEnd\n";
1927             programCollection.spirvAsmSources.add("frag") << src << buildOptionsSpr;
1928         }
1929     }
1930 }
1931 
checkSupport(Context & context) const1932 void EarlyFragmentSampleMaskTest::checkSupport(Context &context) const
1933 {
1934     EarlyFragmentTest::checkSupport(context);
1935 
1936     context.requireDeviceFunctionality("VK_KHR_depth_stencil_resolve");
1937 }
1938 
1939 struct SampleCountTestParams
1940 {
1941     uint32_t sampleCount;
1942     bool earlyAndLate;
1943     bool alphaToCoverage;
1944     bool useMaintenance5;
1945 };
1946 
1947 class EarlyFragmentSampleCountTestInstance : public EarlyFragmentTestInstance
1948 {
1949 public:
1950     EarlyFragmentSampleCountTestInstance(Context &context, const SampleCountTestParams &testParams);
1951 
1952     tcu::TestStatus iterate(void);
1953 
1954 private:
1955     tcu::TextureLevel generateReferenceColorImage(const tcu::TextureFormat format, const tcu::IVec2 &renderSize);
1956 
1957     Move<VkRenderPass> makeRenderPass(const DeviceInterface &vk, const VkDevice device, const VkFormat colorFormat,
1958                                       const VkFormat depthStencilFormat);
1959 
1960     Move<VkPipeline> makeGraphicsPipeline(const DeviceInterface &vk, const VkDevice device,
1961                                           const VkPipelineLayout pipelineLayout, const VkRenderPass renderPass,
1962                                           const VkShaderModule vertexModule, const VkShaderModule fragmentModule,
1963                                           const tcu::IVec2 &renderSize, const VkSampleMask sampleMask);
1964 
1965     const SampleCountTestParams m_testParams;
1966 };
1967 
EarlyFragmentSampleCountTestInstance(Context & context,const SampleCountTestParams & testParams)1968 EarlyFragmentSampleCountTestInstance::EarlyFragmentSampleCountTestInstance(Context &context,
1969                                                                            const SampleCountTestParams &testParams)
1970     : EarlyFragmentTestInstance(context, FLAG_TEST_DEPTH)
1971     , m_testParams(testParams)
1972 {
1973 }
1974 
makeGraphicsPipeline(const DeviceInterface & vk,const VkDevice device,const VkPipelineLayout pipelineLayout,const VkRenderPass renderPass,const VkShaderModule vertexModule,const VkShaderModule fragmentModule,const tcu::IVec2 & renderSize,const VkSampleMask sampleMask)1975 Move<VkPipeline> EarlyFragmentSampleCountTestInstance::makeGraphicsPipeline(
1976     const DeviceInterface &vk, const VkDevice device, const VkPipelineLayout pipelineLayout,
1977     const VkRenderPass renderPass, const VkShaderModule vertexModule, const VkShaderModule fragmentModule,
1978     const tcu::IVec2 &renderSize, const VkSampleMask sampleMask)
1979 {
1980     const std::vector<VkViewport> viewports(1, makeViewport(renderSize));
1981     const std::vector<VkRect2D> scissors(1, makeRect2D(renderSize));
1982 
1983     const VkPipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo = {
1984         VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType                            sType
1985         DE_NULL,                                                    // const void*                                pNext
1986         0u,                                                         // VkPipelineDepthStencilStateCreateFlags    flags
1987         VK_TRUE,            // VkBool32                                    depthTestEnable
1988         VK_TRUE,            // VkBool32                                    depthWriteEnable
1989         VK_COMPARE_OP_LESS, // VkCompareOp                                depthCompareOp
1990         VK_FALSE,           // VkBool32                                    depthBoundsTestEnable
1991         VK_FALSE,           // VkBool32                                    stencilTestEnable
1992         {},                 // VkStencilOpState                            front
1993         {},                 // VkStencilOpState                            back
1994         0.0f,               // float                                    minDepthBounds
1995         1.0f                // float                                    maxDepthBounds
1996     };
1997 
1998     const VkPipelineMultisampleStateCreateInfo multisampleStateCreateInfo = {
1999         VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType                            sType
2000         DE_NULL,                                                  // const void*                                pNext
2001         0u,                                                       // VkPipelineMultisampleStateCreateFlags    flags
2002         (VkSampleCountFlagBits)
2003             m_testParams.sampleCount, // VkSampleCountFlagBits                    rasterizationSamples
2004         false,                        // VkBool32                                    sampleShadingEnable
2005         0.0f,                         // float                                    minSampleShading
2006         &sampleMask,                  // const VkSampleMask*                        pSampleMask
2007         m_testParams.alphaToCoverage, // VkBool32                                    alphaToCoverageEnable
2008         false,                        // VkBool32                                    alphaToOneEnable
2009     };
2010 
2011     return vk::makeGraphicsPipeline(
2012         vk,             // const DeviceInterface&                            vk
2013         device,         // const VkDevice                                    device
2014         pipelineLayout, // const VkPipelineLayout                            pipelineLayout
2015         vertexModule,   // const VkShaderModule                                vertexShaderModule
2016         DE_NULL,        // const VkShaderModule                                tessellationControlModule
2017         DE_NULL,        // const VkShaderModule                                tessellationEvalModule
2018         DE_NULL,        // const VkShaderModule                                geometryShaderModule
2019         fragmentModule, // const VkShaderModule                                fragmentShaderModule
2020         renderPass,     // const VkRenderPass                                renderPass
2021         viewports,      // const std::vector<VkViewport>&                    viewports
2022         scissors,       // const std::vector<VkRect2D>&                        scissors
2023         VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // const VkPrimitiveTopology                        topology
2024         0u,                                  // const uint32_t                                    subpass
2025         0u,                                  // const uint32_t                                    patchControlPoints
2026         DE_NULL,                       // const VkPipelineVertexInputStateCreateInfo*        vertexInputStateCreateInfo
2027         DE_NULL,                       // const VkPipelineRasterizationStateCreateInfo*    rasterizationStateCreateInfo
2028         &multisampleStateCreateInfo,   // const VkPipelineMultisampleStateCreateInfo*        multisampleStateCreateInfo
2029         &depthStencilStateCreateInfo); // const VkPipelineDepthStencilStateCreateInfo*        depthStencilStateCreateInfo
2030 }
2031 
makeRenderPass(const DeviceInterface & vk,const VkDevice device,const VkFormat colorFormat,const VkFormat depthStencilFormat)2032 Move<VkRenderPass> EarlyFragmentSampleCountTestInstance::makeRenderPass(const DeviceInterface &vk,
2033                                                                         const VkDevice device,
2034                                                                         const VkFormat colorFormat,
2035                                                                         const VkFormat depthStencilFormat)
2036 {
2037     const VkAttachmentDescription colorAttachmentDescription = {
2038         (VkAttachmentDescriptionFlags)0,                 // VkAttachmentDescriptionFlags flags;
2039         colorFormat,                                     // VkFormat format;
2040         (VkSampleCountFlagBits)m_testParams.sampleCount, // VkSampleCountFlagBits samples;
2041         VK_ATTACHMENT_LOAD_OP_CLEAR,                     // VkAttachmentLoadOp loadOp;
2042         VK_ATTACHMENT_STORE_OP_STORE,                    // VkAttachmentStoreOp storeOp;
2043         VK_ATTACHMENT_LOAD_OP_DONT_CARE,                 // VkAttachmentLoadOp            stencilLoadOp
2044         VK_ATTACHMENT_STORE_OP_DONT_CARE,                // VkAttachmentStoreOp            stencilStoreOp
2045         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,        // VkImageLayout                initialLayout
2046         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL         // VkImageLayout                finalLayout
2047     };
2048 
2049     const VkAttachmentDescription depthStencilAttachmentDescription = {
2050         (VkAttachmentDescriptionFlags)0,                  // VkStructureType sType;
2051         depthStencilFormat,                               // VkFormat                    format
2052         (VkSampleCountFlagBits)m_testParams.sampleCount,  // VkSampleCountFlagBits    samples
2053         VK_ATTACHMENT_LOAD_OP_CLEAR,                      // VkAttachmentLoadOp        loadOp
2054         VK_ATTACHMENT_STORE_OP_STORE,                     // VkAttachmentStoreOp        storeOp
2055         VK_ATTACHMENT_LOAD_OP_CLEAR,                      // VkAttachmentLoadOp        stencilLoadOp
2056         VK_ATTACHMENT_STORE_OP_STORE,                     // VkAttachmentStoreOp        stencilStoreOp
2057         VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout            initialLayout
2058         VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL  // VkImageLayout            finalLayout
2059     };
2060 
2061     const VkAttachmentDescription resolveAttachmentDescription = {
2062 
2063         (VkAttachmentDescriptionFlags)0,          // VkSubpassDescriptionFlags    flags
2064         colorFormat,                              // VkFormat                        format
2065         VK_SAMPLE_COUNT_1_BIT,                    // VkSampleCountFlagBits        samples
2066         VK_ATTACHMENT_LOAD_OP_CLEAR,              // VkAttachmentLoadOp            loadOp
2067         VK_ATTACHMENT_STORE_OP_STORE,             // VkAttachmentStoreOp            storeOp
2068         VK_ATTACHMENT_LOAD_OP_DONT_CARE,          // VkAttachmentLoadOp            stencilLoadOp
2069         VK_ATTACHMENT_STORE_OP_DONT_CARE,         // VkAttachmentStoreOp            stencilStoreOp
2070         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout                initialLayout
2071         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL  // VkImageLayout                finalLayout
2072     };
2073 
2074     std::vector<VkAttachmentDescription> attachmentDescriptions;
2075 
2076     attachmentDescriptions.push_back(colorAttachmentDescription);
2077     attachmentDescriptions.push_back(depthStencilAttachmentDescription);
2078     attachmentDescriptions.push_back(resolveAttachmentDescription);
2079 
2080     const VkAttachmentReference colorAttachmentRef = {
2081         0u,                                       // uint32_t            attachment
2082         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout    layout
2083     };
2084 
2085     const VkAttachmentReference depthStencilAttachmentRef = {
2086         1u,                                               // uint32_t            attachment
2087         VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout    layout
2088     };
2089 
2090     const VkAttachmentReference resolveAttachmentRef = {
2091         2u,                                       // uint32_t            attachment
2092         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout    layout
2093     };
2094 
2095     const VkSubpassDescription subpassDescription = {
2096         (VkSubpassDescriptionFlags)0,    // VkSubpassDescriptionFlags        flags
2097         VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint                pipelineBindPoint
2098         0u,                              // uint32_t                            inputAttachmentCount
2099         DE_NULL,                         // const VkAttachmentReference2*    pInputAttachments
2100         1u,                              // uint32_t                            colorAttachmentCount
2101         &colorAttachmentRef,             // const VkAttachmentReference2*    pColorAttachments
2102         &resolveAttachmentRef,           // const VkAttachmentReference2*    pResolveAttachments
2103         &depthStencilAttachmentRef,      // const VkAttachmentReference2*    pDepthStencilAttachment
2104         0u,                              // uint32_t                            preserveAttachmentCount
2105         DE_NULL                          // const uint32_t*                    pPreserveAttachments
2106     };
2107 
2108     const VkRenderPassCreateInfo renderPassInfo = {
2109         VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
2110         DE_NULL,                                   // const void* pNext;
2111         (VkRenderPassCreateFlags)0,                // VkRenderPassCreateFlags flags;
2112         (uint32_t)attachmentDescriptions.size(),   // uint32_t attachmentCount;
2113         attachmentDescriptions.data(),             // const VkAttachmentDescription* pAttachments;
2114         1u,                                        // uint32_t subpassCount;
2115         &subpassDescription,                       // const VkSubpassDescription* pSubpasses;
2116         0u,                                        // uint32_t dependencyCount;
2117         DE_NULL                                    // const VkSubpassDependency* pDependencies;
2118     };
2119 
2120     return createRenderPass(vk, device, &renderPassInfo, DE_NULL);
2121 }
2122 
generateReferenceColorImage(const tcu::TextureFormat format,const tcu::IVec2 & renderSize)2123 tcu::TextureLevel EarlyFragmentSampleCountTestInstance::generateReferenceColorImage(const tcu::TextureFormat format,
2124                                                                                     const tcu::IVec2 &renderSize)
2125 {
2126     tcu::TextureLevel image(format, renderSize.x(), renderSize.y());
2127     const tcu::Vec4 clearColor = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
2128 
2129     tcu::clear(image.getAccess(), clearColor);
2130 
2131     return image;
2132 }
2133 
iterate(void)2134 tcu::TestStatus EarlyFragmentSampleCountTestInstance::iterate(void)
2135 {
2136     const DeviceInterface &vk       = m_context.getDeviceInterface();
2137     const VkDevice device           = m_context.getDevice();
2138     const VkQueue queue             = m_context.getUniversalQueue();
2139     const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
2140     Allocator &allocator            = m_context.getDefaultAllocator();
2141     const VkFormat colorFormat      = VK_FORMAT_R8G8B8A8_UNORM;
2142     const VkFormat depthFormat      = VK_FORMAT_D16_UNORM;
2143     VkQueryPool queryPool;
2144     const uint32_t queryCount = 2u;
2145     std::vector<VkDeviceSize> sampleCounts(queryCount);
2146 
2147     // Create a query pool for storing the occlusion query result
2148     {
2149         VkQueryPoolCreateInfo queryPoolInfo{
2150             VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, // VkStructureType sType;
2151             DE_NULL,                                  // const void* pNext;
2152             (VkQueryPoolCreateFlags)0,                // VkQueryPoolCreateFlags flags;
2153             VK_QUERY_TYPE_OCCLUSION,                  // VkQueryType queryType;
2154             queryCount,                               // uint32_t queryCount;
2155             0u,                                       // VkQueryPipelineStatisticFlags pipelineStatistics;
2156         };
2157 
2158         VK_CHECK(vk.createQueryPool(device, &queryPoolInfo, NULL, &queryPool));
2159     }
2160 
2161     m_context.getTestContext().getLog() << tcu::TestLog::Message << "Using depth format "
2162                                         << getFormatName(VK_FORMAT_D16_UNORM) << tcu::TestLog::EndMessage;
2163 
2164     // Color attachment
2165     const tcu::IVec2 renderSize = tcu::IVec2(32, 32);
2166     const VkImageSubresourceRange colorSubresourceRange =
2167         makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
2168 
2169     const VkImageCreateInfo imageParams = {
2170         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,             // VkStructureType sType;
2171         DE_NULL,                                         // const void* pNext;
2172         (VkImageCreateFlags)0,                           // VkImageCreateFlags flags;
2173         VK_IMAGE_TYPE_2D,                                // VkImageType imageType;
2174         colorFormat,                                     // VkFormat format;
2175         makeExtent3D(renderSize.x(), renderSize.y(), 1), // VkExtent3D extent;
2176         1u,                                              // uint32_t mipLevels;
2177         1u,                                              // uint32_t arrayLayers;
2178         (VkSampleCountFlagBits)m_testParams.sampleCount, // VkSampleCountFlagBits samples;
2179         VK_IMAGE_TILING_OPTIMAL,                         // VkImageTiling tiling;
2180         VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,             // VkImageUsageFlags usage;
2181         VK_SHARING_MODE_EXCLUSIVE,                       // VkSharingMode sharingMode;
2182         0u,                                              // uint32_t queueFamilyIndexCount;
2183         DE_NULL,                                         // const uint32_t* pQueueFamilyIndices;
2184         VK_IMAGE_LAYOUT_UNDEFINED,                       // VkImageLayout initialLayout;
2185     };
2186 
2187     const Unique<VkImage> colorImage(makeImage(vk, device, imageParams));
2188     const UniquePtr<Allocation> colorImageAlloc(bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any));
2189     const Unique<VkImageView> colorImageView(
2190         makeImageView(vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange));
2191 
2192     const Unique<VkImage> resolveColorImage(
2193         makeImage(vk, device,
2194                   makeImageCreateInfo(renderSize, colorFormat,
2195                                       VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
2196     const UniquePtr<Allocation> resolveColorImageAlloc(
2197         bindImage(vk, device, allocator, *resolveColorImage, MemoryRequirement::Any));
2198     const Unique<VkImageView> resolveColorImageView(
2199         makeImageView(vk, device, *resolveColorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange));
2200 
2201     // Depth-Stencil attachment
2202     const VkImageSubresourceRange depthSubresourceRange =
2203         makeImageSubresourceRange(getImageAspectFlags(depthFormat), 0u, 1u, 0u, 1u);
2204 
2205     const VkImageCreateInfo depthImageParams = {
2206         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,             // VkStructureType sType;
2207         DE_NULL,                                         // const void* pNext;
2208         (VkImageCreateFlags)0,                           // VkImageCreateFlags flags;
2209         VK_IMAGE_TYPE_2D,                                // VkImageType imageType;
2210         depthFormat,                                     // VkFormat format;
2211         makeExtent3D(renderSize.x(), renderSize.y(), 1), // VkExtent3D extent;
2212         1u,                                              // uint32_t mipLevels;
2213         1u,                                              // uint32_t arrayLayers;
2214         (VkSampleCountFlagBits)m_testParams.sampleCount, // VkSampleCountFlagBits samples;
2215         VK_IMAGE_TILING_OPTIMAL,                         // VkImageTiling tiling;
2216         VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,     // VkImageUsageFlags usage;
2217         VK_SHARING_MODE_EXCLUSIVE,                       // VkSharingMode sharingMode;
2218         0u,                                              // uint32_t queueFamilyIndexCount;
2219         DE_NULL,                                         // const uint32_t* pQueueFamilyIndices;
2220         VK_IMAGE_LAYOUT_UNDEFINED,                       // VkImageLayout initialLayout;
2221     };
2222 
2223     const Unique<VkImage> depthImage(makeImage(vk, device, depthImageParams));
2224     const UniquePtr<Allocation> depthImageAlloc(bindImage(vk, device, allocator, *depthImage, MemoryRequirement::Any));
2225     const Unique<VkImageView> depthImageView(
2226         makeImageView(vk, device, *depthImage, VK_IMAGE_VIEW_TYPE_2D, depthFormat, depthSubresourceRange));
2227 
2228     const VkImageView attachmentImages[]   = {*colorImageView, *depthImageView, *resolveColorImageView};
2229     const uint32_t numUsedAttachmentImages = DE_LENGTH_OF_ARRAY(attachmentImages);
2230 
2231     // Vertex buffer
2232     const uint32_t numVertices               = 6u;
2233     const VkDeviceSize vertexBufferSizeBytes = 256 * numVertices;
2234     const Unique<VkBuffer> vertexBuffer(
2235         makeBuffer(vk, device, vertexBufferSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
2236     const UniquePtr<Allocation> vertexBufferAlloc(
2237         bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible));
2238 
2239     {
2240         tcu::Vec4 *const pVertices = reinterpret_cast<tcu::Vec4 *>(vertexBufferAlloc->getHostPtr());
2241 
2242         pVertices[0] = tcu::Vec4(1.0f, -1.0f, 0.0f, 1.0f);
2243         pVertices[1] = tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f);
2244         pVertices[2] = tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f);
2245 
2246         pVertices[3] = tcu::Vec4(-1.0f, 1.0f, 1.0f, 1.0f);
2247         pVertices[4] = tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f);
2248         pVertices[5] = tcu::Vec4(1.0f, -1.0f, 1.0f, 1.0f);
2249 
2250         flushAlloc(vk, device, *vertexBufferAlloc);
2251         // No barrier needed, flushed memory is automatically visible
2252     }
2253 
2254     // Render result buffer (to retrieve color attachment contents)
2255 
2256     const VkDeviceSize colorBufferSizeBytes =
2257         tcu::getPixelSize(mapVkFormat(colorFormat)) * renderSize.x() * renderSize.y();
2258     const Unique<VkBuffer> colorBufferNoEarlyResults(
2259         makeBuffer(vk, device, colorBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
2260     const UniquePtr<Allocation> colorBufferAllocNoEarly(
2261         bindBuffer(vk, device, allocator, *colorBufferNoEarlyResults, MemoryRequirement::HostVisible));
2262     const Unique<VkBuffer> colorBufferEarlyResults(
2263         makeBuffer(vk, device, colorBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
2264     const UniquePtr<Allocation> colorBufferAllocEarly(
2265         bindBuffer(vk, device, allocator, *colorBufferEarlyResults, MemoryRequirement::HostVisible));
2266 
2267     // Pipeline
2268 
2269     const Unique<VkShaderModule> vertexModule(
2270         createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
2271     const Unique<VkShaderModule> fragmentModuleNoEarly(
2272         createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u));
2273     const Unique<VkShaderModule> fragmentModuleEarlyFrag(
2274         createShaderModule(vk, device, m_context.getBinaryCollection().get("frag_early"), 0u));
2275 
2276     const Unique<VkRenderPass> renderPass(makeRenderPass(vk, device, colorFormat, depthFormat));
2277 
2278     const Unique<VkFramebuffer> framebuffer(makeFramebuffer(vk, device, *renderPass, numUsedAttachmentImages,
2279                                                             attachmentImages, renderSize.x(), renderSize.y()));
2280 
2281     const Unique<VkPipelineLayout> pipelineLayout(makePipelineLayout(vk, device, DE_NULL));
2282 
2283     // When we are creating a pipeline for runs without early fragment test, we are enabling all the samples for full coverage.
2284     // Sample mask will be modified in a fragment shader.
2285     const Unique<VkPipeline> pipelineNoEarlyFrag(makeGraphicsPipeline(
2286         vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModuleNoEarly, renderSize, 0xFFFFFFFF));
2287 
2288     // For early fragment tests, we are enabling only half of the samples.
2289     const Unique<VkPipeline> pipelineEarlyFrag(makeGraphicsPipeline(
2290         vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModuleEarlyFrag, renderSize, 0xAAAAAAAA));
2291 
2292     // Build a command buffer
2293 
2294     const Unique<VkCommandPool> cmdPool(
2295         createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
2296     const Unique<VkCommandBuffer> cmdBuffer(
2297         allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
2298 
2299     enum QueryIndex
2300     {
2301         QUERY_INDEX_NO_EARLY_FRAG = 0,
2302         QUERY_INDEX_EARLY_FRAG    = 1
2303     };
2304 
2305     {
2306         const VkRect2D renderArea = {
2307             makeOffset2D(0, 0),
2308             makeExtent2D(renderSize.x(), renderSize.y()),
2309         };
2310 
2311         const tcu::Vec4 clearColor(0.0f, 0.0f, 0.0f, 1.0f);
2312         const VkDeviceSize vertexBufferOffset = 0ull;
2313 
2314         beginCommandBuffer(vk, *cmdBuffer);
2315 
2316         // transition images to proper layouts - this cant be done with renderpass as we will use same renderpass twice
2317         const VkImageMemoryBarrier initialImageBarriers[]{
2318             makeImageMemoryBarrier(0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
2319                                    VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, *colorImage, colorSubresourceRange),
2320             makeImageMemoryBarrier(0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
2321                                    VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, *resolveColorImage, colorSubresourceRange),
2322             makeImageMemoryBarrier(0, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
2323                                    VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, *depthImage,
2324                                    depthSubresourceRange)};
2325         vk.cmdPipelineBarrier(*cmdBuffer, 0, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u,
2326                               DE_NULL, 2u, initialImageBarriers);
2327         vk.cmdPipelineBarrier(*cmdBuffer, 0, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL,
2328                               1u, &initialImageBarriers[2]);
2329 
2330         const VkClearValue clearValues[] = {
2331             makeClearValueColor(clearColor),      // attachment 0
2332             makeClearValueDepthStencil(0.5f, 3u), // attachment 1
2333             makeClearValueColor(clearColor),      // attachment 2
2334             makeClearValueDepthStencil(0.5f, 3u), // attachment 3
2335         };
2336 
2337         const VkRenderPassBeginInfo renderPassBeginInfo = {
2338             VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
2339             DE_NULL,                                  // const void* pNext;
2340             *renderPass,                              // VkRenderPass renderPass;
2341             *framebuffer,                             // VkFramebuffer framebuffer;
2342             renderArea,                               // VkRect2D renderArea;
2343             DE_LENGTH_OF_ARRAY(clearValues),          // uint32_t clearValueCount;
2344             clearValues,                              // const VkClearValue* pClearValues;
2345         };
2346 
2347         // Reset query pool. Must be done outside of render pass
2348         vk.cmdResetQueryPool(*cmdBuffer, queryPool, 0, queryCount);
2349 
2350         vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
2351 
2352         vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
2353 
2354         // Run without early fragment test.
2355         vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineNoEarlyFrag);
2356 
2357         vk.cmdBeginQuery(cmdBuffer.get(), queryPool, QUERY_INDEX_NO_EARLY_FRAG, VK_QUERY_CONTROL_PRECISE_BIT);
2358         vk.cmdDraw(*cmdBuffer, numVertices, 1u, 0u, 0u);
2359         vk.cmdEndQuery(cmdBuffer.get(), queryPool, QUERY_INDEX_NO_EARLY_FRAG);
2360 
2361         endRenderPass(vk, *cmdBuffer);
2362 
2363         copyImageToBuffer(vk, *cmdBuffer, *resolveColorImage, *colorBufferNoEarlyResults, renderSize,
2364                           VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
2365 
2366         // after copying from resolved image we need to switch its layout back to color attachment optimal
2367         const VkImageMemoryBarrier postResolveImageBarrier = makeImageMemoryBarrier(
2368             VK_ACCESS_TRANSFER_READ_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
2369             VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, *resolveColorImage, colorSubresourceRange);
2370         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
2371                               0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &postResolveImageBarrier);
2372 
2373         vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
2374 
2375         vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
2376 
2377         // Run with early fragment test.
2378         vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineEarlyFrag);
2379 
2380         vk.cmdBeginQuery(cmdBuffer.get(), queryPool, QUERY_INDEX_EARLY_FRAG, VK_QUERY_CONTROL_PRECISE_BIT);
2381         vk.cmdDraw(*cmdBuffer, numVertices, 1u, 0u, 0u);
2382         vk.cmdEndQuery(cmdBuffer.get(), queryPool, QUERY_INDEX_EARLY_FRAG);
2383 
2384         endRenderPass(vk, *cmdBuffer);
2385 
2386         copyImageToBuffer(vk, *cmdBuffer, *resolveColorImage, *colorBufferEarlyResults, renderSize,
2387                           VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
2388 
2389         endCommandBuffer(vk, *cmdBuffer);
2390         submitCommandsAndWait(vk, device, queue, *cmdBuffer);
2391     }
2392 
2393     // When early fragment test is enabled, all samples are killed in fragment shader. The result color should be black.
2394     {
2395         invalidateAlloc(vk, device, *colorBufferAllocEarly);
2396 
2397         const tcu::ConstPixelBufferAccess imagePixelAccess(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1,
2398                                                            colorBufferAllocEarly->getHostPtr());
2399         const tcu::TextureLevel referenceImage = generateReferenceColorImage(mapVkFormat(colorFormat), renderSize);
2400 
2401         if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Compare color output",
2402                                         "Early fragment image result comparison", referenceImage.getAccess(),
2403                                         imagePixelAccess, tcu::Vec4(0.02f), tcu::COMPARE_LOG_RESULT))
2404             return tcu::TestStatus::fail("Rendered color image is not correct");
2405     }
2406 
2407     // The image has 32x32 pixels and each pixel has m_sampleCount samples. Half of these samples are discarded before sample counting.
2408     // This means the reference value for passed samples is ((32 x 32) / 2 / 2) * sampleCount.
2409     {
2410         uint64_t refValue  = uint64_t(uint32_t((renderSize.x() * renderSize.y()) / 4) * m_testParams.sampleCount);
2411         uint64_t tolerance = uint64_t(refValue * 5 / 100);
2412         uint64_t minValue  = refValue - tolerance;
2413         uint64_t maxValue  = refValue + tolerance;
2414 
2415         VK_CHECK(vk.getQueryPoolResults(device, queryPool, 0u, queryCount, queryCount * sizeof(VkDeviceSize),
2416                                         sampleCounts.data(), sizeof(VkDeviceSize),
2417                                         VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
2418 
2419         // Log test results
2420         {
2421             tcu::TestLog &log = m_context.getTestContext().getLog();
2422 
2423             log << tcu::TestLog::Message << "\nAcceptable range: " << minValue << " - " << maxValue
2424                 << tcu::TestLog::EndMessage;
2425             log << tcu::TestLog::Message
2426                 << "Passed Samples (without early fragment test) : " << de::toString(sampleCounts[0])
2427                 << tcu::TestLog::EndMessage;
2428             log << tcu::TestLog::Message
2429                 << "Passed Samples (with early fragment test)    : " << de::toString(sampleCounts[1])
2430                 << tcu::TestLog::EndMessage;
2431         }
2432 
2433 #ifndef CTS_USES_VULKANSC
2434         vk.destroyQueryPool(device, queryPool, nullptr);
2435 #endif // CTS_USES_VULKANSC
2436 
2437         // Check that number of the all passed samples are within an acceptable range.
2438         if (sampleCounts[QUERY_INDEX_NO_EARLY_FRAG] >= minValue &&
2439             sampleCounts[QUERY_INDEX_NO_EARLY_FRAG] <= maxValue && sampleCounts[QUERY_INDEX_EARLY_FRAG] >= minValue &&
2440             sampleCounts[QUERY_INDEX_EARLY_FRAG] <= maxValue)
2441         {
2442             return tcu::TestStatus::pass("Success");
2443         }
2444         else if (sampleCounts[QUERY_INDEX_NO_EARLY_FRAG] >= minValue &&
2445                  sampleCounts[QUERY_INDEX_NO_EARLY_FRAG] <= maxValue && sampleCounts[QUERY_INDEX_EARLY_FRAG] == 0)
2446         {
2447 #ifndef CTS_USES_VULKANSC
2448             if (m_testParams.useMaintenance5)
2449             {
2450                 if (m_context.getMaintenance5Properties().earlyFragmentMultisampleCoverageAfterSampleCounting)
2451                     return tcu::TestStatus::fail("Fail");
2452                 return tcu::TestStatus::pass("Pass");
2453             }
2454 #endif
2455             // Spec says: "If the fragment shader declares the EarlyFragmentTests execution mode, fragment shading and
2456             // multisample coverage operations should instead be performed after sample counting.
2457 
2458             // since the specification says 'should', the opposite behavior is allowed, but not preferred
2459             return tcu::TestStatus(
2460                 QP_TEST_RESULT_QUALITY_WARNING,
2461                 "Sample count is 0 - sample counting performed after multisample coverage and fragment shading");
2462         }
2463         else if (sampleCounts[QUERY_INDEX_NO_EARLY_FRAG] >= minValue &&
2464                  sampleCounts[QUERY_INDEX_NO_EARLY_FRAG] <= maxValue &&
2465                  sampleCounts[QUERY_INDEX_EARLY_FRAG] >= (minValue * 2) &&
2466                  sampleCounts[QUERY_INDEX_EARLY_FRAG] <= (maxValue * 2))
2467         {
2468             // If the sample count returned is double the expected value, the sample mask test has been executed after
2469             // sample counting.
2470 
2471 #ifndef CTS_USES_VULKANSC
2472             if (m_testParams.useMaintenance5)
2473             {
2474                 if (m_context.getMaintenance5Properties().earlyFragmentSampleMaskTestBeforeSampleCounting)
2475                     return tcu::TestStatus::fail("Fail");
2476                 return tcu::TestStatus::pass("Pass");
2477             }
2478 #endif
2479             // Spec says: "If there is a fragment shader and it declares the EarlyFragmentTests execution mode, ...
2480             // sample mask test may: instead be performed after sample counting"
2481 
2482             // since the specification says 'may', the opposite behavior is allowed, but not preferred
2483             return tcu::TestStatus(
2484                 QP_TEST_RESULT_QUALITY_WARNING,
2485                 "Sample count is greater than expected - sample mask test performed after sample counting");
2486         }
2487         else
2488         {
2489             // Log no early frag test images
2490             {
2491                 tcu::TestLog &log = m_context.getTestContext().getLog();
2492 
2493                 invalidateAlloc(vk, device, *colorBufferAllocNoEarly);
2494 
2495                 const tcu::ConstPixelBufferAccess imagePixelAccess(
2496                     mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1, colorBufferAllocNoEarly->getHostPtr());
2497 
2498                 log << tcu::LogImageSet("No Early Frag Test Images", "No Early Fragment Test Images")
2499                     << tcu::TestLog::Image("color", "Rendered image (color)", imagePixelAccess)
2500                     << tcu::TestLog::EndImageSet;
2501             }
2502 
2503             // Log early frag test images
2504             {
2505                 tcu::TestLog &log = m_context.getTestContext().getLog();
2506 
2507                 invalidateAlloc(vk, device, *colorBufferAllocEarly);
2508 
2509                 const tcu::ConstPixelBufferAccess imagePixelAccess(
2510                     mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1, colorBufferAllocEarly->getHostPtr());
2511 
2512                 log << tcu::LogImageSet("Early Frag Test Images", "Early Fragment Test Images")
2513                     << tcu::TestLog::Image("color", "Rendered image (color)", imagePixelAccess)
2514                     << tcu::TestLog::EndImageSet;
2515             }
2516 
2517             return tcu::TestStatus::fail("Sample count value outside expected range.");
2518         }
2519     }
2520 }
2521 
2522 class EarlyFragmentSampleCountTest : public EarlyFragmentTest
2523 {
2524 public:
2525     EarlyFragmentSampleCountTest(tcu::TestContext &testCtx, const std::string name,
2526                                  const SampleCountTestParams &testParams);
2527 
2528     void initPrograms(SourceCollections &programCollection) const override;
2529     TestInstance *createInstance(Context &context) const override;
2530     void checkSupport(Context &context) const override;
2531 
2532 private:
2533     const SampleCountTestParams m_testParams;
2534 };
2535 
EarlyFragmentSampleCountTest(tcu::TestContext & testCtx,const std::string name,const SampleCountTestParams & testParams)2536 EarlyFragmentSampleCountTest::EarlyFragmentSampleCountTest(tcu::TestContext &testCtx, const std::string name,
2537                                                            const SampleCountTestParams &testParams)
2538     : EarlyFragmentTest(testCtx, name, FLAG_TEST_DEPTH)
2539     , m_testParams(testParams)
2540 {
2541 }
2542 
createInstance(Context & context) const2543 TestInstance *EarlyFragmentSampleCountTest::createInstance(Context &context) const
2544 {
2545     return new EarlyFragmentSampleCountTestInstance(context, m_testParams);
2546 }
2547 
initPrograms(SourceCollections & programCollection) const2548 void EarlyFragmentSampleCountTest::initPrograms(SourceCollections &programCollection) const
2549 {
2550     // Vertex shader
2551     {
2552         std::ostringstream vrt;
2553 
2554         vrt << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2555             << "\n"
2556             << "layout(location = 0) in highp vec4 position;\n"
2557             << "\n"
2558             << "out gl_PerVertex {\n"
2559             << "   vec4 gl_Position;\n"
2560             << "};\n"
2561             << "\n"
2562             << "void main (void)\n"
2563             << "{\n"
2564             << "    gl_Position = position;\n"
2565             << "}\n";
2566 
2567         programCollection.glslSources.add("vert") << glu::VertexSource(vrt.str());
2568     }
2569 
2570     // Fragment shader for runs without early fragment test
2571     if (m_testParams.earlyAndLate == false)
2572     {
2573         std::ostringstream frg;
2574 
2575         frg << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2576             << "\n"
2577             << "layout(location = 0) out highp vec4 fragColor;\n"
2578             << "\n"
2579             << "void main (void)\n"
2580             << "{\n"
2581             << "    // This will kill half of the samples.\n"
2582             << "    gl_SampleMask[0] = 0xAAAAAAAA;\n"
2583             << "    fragColor = vec4(1.0, 1.0, 0.0, 1.0);\n"
2584             << "}\n";
2585 
2586         programCollection.glslSources.add("frag") << glu::FragmentSource(frg.str());
2587     }
2588     else
2589     {
2590         const SpirVAsmBuildOptions buildOptionsSpr(programCollection.usedVulkanVersion, SPIRV_VERSION_1_3);
2591         const std::string src = "; SPIR - V\n"
2592                                 "; Version: 1.0\n"
2593                                 "; Generator: Khronos Glslang Reference Front End; 10\n"
2594                                 "; Bound: 23\n"
2595                                 "; Schema: 0\n"
2596                                 "OpCapability Shader\n"
2597                                 "OpExtension \"SPV_AMD_shader_early_and_late_fragment_tests\"\n"
2598                                 "%1 = OpExtInstImport \"GLSL.std.450\"\n"
2599                                 "OpMemoryModel Logical GLSL450\n"
2600                                 "OpEntryPoint Fragment %4 \"main\" %11 %19\n"
2601                                 "OpExecutionMode %4 OriginUpperLeft\n"
2602                                 "OpExecutionMode %4 EarlyAndLateFragmentTestsAMD\n"
2603                                 "OpExecutionMode %4 DepthReplacing\n"
2604                                 "OpExecutionMode %4 DepthLess\n"
2605                                 "OpDecorate %11 BuiltIn SampleMask\n"
2606                                 "OpDecorate %19 Location 0\n"
2607                                 "%2 = OpTypeVoid\n"
2608                                 "%3 = OpTypeFunction %2\n"
2609                                 "%6 = OpTypeInt 32 1\n"
2610                                 "%7 = OpTypeInt 32 0\n"
2611                                 "%8 = OpConstant %7 1\n"
2612                                 "%9 = OpTypeArray %6 %8\n"
2613                                 "%10 = OpTypePointer Output %9\n"
2614                                 "%11 = OpVariable %10 Output\n"
2615                                 "%12 = OpConstant %6 0\n"
2616                                 "%13 = OpConstant %6 -1431655766\n"
2617                                 "%14 = OpTypePointer Output %6\n"
2618                                 "%16 = OpTypeFloat 32\n"
2619                                 "%17 = OpTypeVector %16 4\n"
2620                                 "%18 = OpTypePointer Output %17\n"
2621                                 "%19 = OpVariable %18 Output\n"
2622                                 "%20 = OpConstant %16 1\n"
2623                                 "%21 = OpConstant %16 0\n"
2624                                 "%22 = OpConstantComposite %17 %20 %20 %21 %20\n"
2625                                 "%4 = OpFunction %2 None %3\n"
2626                                 "%5 = OpLabel\n"
2627                                 "%15 = OpAccessChain %14 %11 %12\n"
2628                                 "OpStore %15 %13\n"
2629                                 "OpStore %19 %22\n"
2630                                 "OpReturn\n"
2631                                 "OpFunctionEnd\n";
2632         programCollection.spirvAsmSources.add("frag") << src << buildOptionsSpr;
2633     }
2634 
2635     // Fragment shader for early fragment tests
2636     if (m_testParams.earlyAndLate == false)
2637     {
2638         std::ostringstream frg;
2639 
2640         frg << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2641             << "\n"
2642             << "layout(early_fragment_tests) in;\n"
2643             << "\n"
2644             << "layout(location = 0) out highp vec4 fragColor;\n"
2645             << "\n"
2646             << "void main (void)\n"
2647             << "{\n";
2648 
2649         if (m_testParams.alphaToCoverage)
2650         {
2651             frg << "    // alphaToCoverageEnable = TRUE and emitting 0 alpha kills all the samples, but the sample "
2652                    "counting has already happened.\n"
2653                 << "    fragColor = vec4(1.0, 1.0, 0.0, 0.0);\n"
2654                 << "}\n";
2655         }
2656         else
2657         {
2658             frg << "    // Sample mask kills all the samples, but the sample counting has already happened.\n"
2659                 << "    gl_SampleMask[0] = 0x0;\n"
2660                 << "    fragColor = vec4(1.0, 1.0, 0.0, 1.0);\n"
2661                 << "}\n";
2662         }
2663 
2664         programCollection.glslSources.add("frag_early") << glu::FragmentSource(frg.str());
2665     }
2666     else
2667     {
2668         const SpirVAsmBuildOptions buildOptionsSpr(programCollection.usedVulkanVersion, SPIRV_VERSION_1_3);
2669         const std::string src = "; SPIR - V\n"
2670                                 "; Version: 1.0\n"
2671                                 "; Generator: Khronos Glslang Reference Front End; 10\n"
2672                                 "; Bound: 22\n"
2673                                 "; Schema: 0\n"
2674                                 "OpCapability Shader\n"
2675                                 "OpExtension \"SPV_AMD_shader_early_and_late_fragment_tests\"\n"
2676                                 "%1 = OpExtInstImport \"GLSL.std.450\"\n"
2677                                 "OpMemoryModel Logical GLSL450\n"
2678                                 "OpEntryPoint Fragment %4 \"main\" %11 %18\n"
2679                                 "OpExecutionMode %4 OriginUpperLeft\n"
2680                                 "OpExecutionMode %4 EarlyAndLateFragmentTestsAMD\n"
2681                                 "OpDecorate %11 BuiltIn SampleMask\n"
2682                                 "OpDecorate %18 Location 0\n"
2683                                 "%2 = OpTypeVoid\n"
2684                                 "%3 = OpTypeFunction %2\n"
2685                                 "%6 = OpTypeInt 32 1\n"
2686                                 "%7 = OpTypeInt 32 0\n"
2687                                 "%8 = OpConstant %7 1\n"
2688                                 "%9 = OpTypeArray %6 %8\n"
2689                                 "%10 = OpTypePointer Output %9\n"
2690                                 "%11 = OpVariable %10 Output\n"
2691                                 "%12 = OpConstant %6 0\n"
2692                                 "%13 = OpTypePointer Output %6\n"
2693                                 "%15 = OpTypeFloat 32\n"
2694                                 "%16 = OpTypeVector %15 4\n"
2695                                 "%17 = OpTypePointer Output %16\n"
2696                                 "%18 = OpVariable %17 Output\n"
2697                                 "%19 = OpConstant %15 1\n"
2698                                 "%20 = OpConstant %15 0\n"
2699                                 "%21 = OpConstantComposite %16 %19 %19 %20 %19\n"
2700                                 "%4 = OpFunction %2 None %3\n"
2701                                 "%5 = OpLabel\n"
2702                                 "%14 = OpAccessChain %13 %11 %12\n"
2703                                 "OpStore %14 %12\n"
2704                                 "OpStore %18 %21\n"
2705                                 "OpReturn\n"
2706                                 "OpFunctionEnd\n";
2707         programCollection.spirvAsmSources.add("frag_early") << src << buildOptionsSpr;
2708     }
2709 }
2710 
checkSupport(Context & context) const2711 void EarlyFragmentSampleCountTest::checkSupport(Context &context) const
2712 {
2713     EarlyFragmentTest::checkSupport(context);
2714 
2715     // Check support for MSAA image formats used in the test.
2716     const InstanceInterface &vki      = context.getInstanceInterface();
2717     const VkPhysicalDevice physDevice = context.getPhysicalDevice();
2718     const VkFormat colorFormat        = VK_FORMAT_R8G8B8A8_UNORM;
2719     const VkFormat depthFormat        = VK_FORMAT_D16_UNORM;
2720 
2721     VkImageFormatProperties formatProperties;
2722 
2723     vki.getPhysicalDeviceImageFormatProperties(physDevice, colorFormat, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
2724                                                VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
2725                                                0u, &formatProperties);
2726     if ((formatProperties.sampleCounts & m_testParams.sampleCount) == 0)
2727         TCU_THROW(NotSupportedError, "Format does not support this number of samples for color format");
2728 
2729     vki.getPhysicalDeviceImageFormatProperties(
2730         physDevice, depthFormat, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
2731         VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 0u, &formatProperties);
2732     if ((formatProperties.sampleCounts & m_testParams.sampleCount) == 0)
2733         TCU_THROW(NotSupportedError, "Format does not support this number of samples for depth format");
2734 
2735     if (!context.getDeviceFeatures().occlusionQueryPrecise)
2736         TCU_THROW(NotSupportedError, "Precise occlusion queries are not supported");
2737 
2738 #ifndef CTS_USES_VULKANSC
2739     if (m_testParams.earlyAndLate)
2740     {
2741         context.requireDeviceFunctionality("VK_AMD_shader_early_and_late_fragment_tests");
2742         if (context.getShaderEarlyAndLateFragmentTestsFeaturesAMD().shaderEarlyAndLateFragmentTests == VK_FALSE)
2743             TCU_THROW(NotSupportedError, "shaderEarlyAndLateFragmentTests is not supported");
2744     }
2745 
2746     if (m_testParams.useMaintenance5)
2747         context.requireDeviceFunctionality("VK_KHR_maintenance5");
2748 #endif
2749 }
2750 
2751 } // namespace
2752 
createEarlyFragmentTests(tcu::TestContext & testCtx)2753 tcu::TestCaseGroup *createEarlyFragmentTests(tcu::TestContext &testCtx)
2754 {
2755     de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "early_fragment"));
2756 
2757     {
2758         struct TestCaseEarly
2759         {
2760             std::string caseName;
2761             uint32_t flags;
2762         };
2763 
2764         static const TestCaseEarly cases[] = {
2765 
2766             {"no_early_fragment_tests_depth", FLAG_TEST_DEPTH | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS},
2767             {"no_early_fragment_tests_stencil", FLAG_TEST_STENCIL | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS},
2768             {"early_fragment_tests_depth", FLAG_TEST_DEPTH},
2769             {"early_fragment_tests_stencil", FLAG_TEST_STENCIL},
2770             {"no_early_fragment_tests_depth_no_attachment",
2771              FLAG_TEST_DEPTH | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS | FLAG_DONT_USE_TEST_ATTACHMENT},
2772             {"no_early_fragment_tests_stencil_no_attachment",
2773              FLAG_TEST_STENCIL | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS | FLAG_DONT_USE_TEST_ATTACHMENT},
2774             {"early_fragment_tests_depth_no_attachment", FLAG_TEST_DEPTH | FLAG_DONT_USE_TEST_ATTACHMENT},
2775             {"early_fragment_tests_stencil_no_attachment", FLAG_TEST_STENCIL | FLAG_DONT_USE_TEST_ATTACHMENT},
2776         };
2777 
2778 #ifndef CTS_USES_VULKANSC
2779         static const TestCaseEarly casesEarlyAndLate[] = {
2780             {"early_and_late_fragment_tests_depth", FLAG_TEST_DEPTH | FLAG_EARLY_AND_LATE_FRAGMENT_TESTS},
2781             {"early_and_late_fragment_tests_stencil", FLAG_TEST_STENCIL | FLAG_EARLY_AND_LATE_FRAGMENT_TESTS},
2782             {"early_and_late_fragment_tests_depth_no_attachment",
2783              FLAG_TEST_DEPTH | FLAG_DONT_USE_TEST_ATTACHMENT | FLAG_EARLY_AND_LATE_FRAGMENT_TESTS},
2784             {"early_and_late_fragment_tests_stencil_no_attachment",
2785              FLAG_TEST_STENCIL | FLAG_DONT_USE_TEST_ATTACHMENT | FLAG_EARLY_AND_LATE_FRAGMENT_TESTS},
2786         };
2787 #endif
2788 
2789         for (int i = 0; i < DE_LENGTH_OF_ARRAY(cases); ++i)
2790             testGroup->addChild(new EarlyFragmentTest(testCtx, cases[i].caseName, cases[i].flags));
2791 #ifndef CTS_USES_VULKANSC
2792         for (int i = 0; i < DE_LENGTH_OF_ARRAY(casesEarlyAndLate); ++i)
2793             testGroup->addChild(
2794                 new EarlyFragmentTest(testCtx, casesEarlyAndLate[i].caseName, casesEarlyAndLate[i].flags));
2795 #endif
2796     }
2797 
2798     // Check that discard does not affect depth test writes.
2799     {
2800         static const struct
2801         {
2802             std::string caseName;
2803             uint32_t flags;
2804         } cases[] = {
2805             {"discard_no_early_fragment_tests_depth", FLAG_TEST_DEPTH | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS},
2806             {"discard_no_early_fragment_tests_stencil", FLAG_TEST_STENCIL | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS},
2807             {"discard_early_fragment_tests_depth", FLAG_TEST_DEPTH},
2808             {"discard_early_fragment_tests_stencil", FLAG_TEST_STENCIL},
2809 #ifndef CTS_USES_VULKANSC
2810             {"discard_early_and_late_fragment_tests_depth",
2811              FLAG_TEST_DEPTH | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS | FLAG_EARLY_AND_LATE_FRAGMENT_TESTS},
2812             {"discard_early_and_late_fragment_tests_stencil",
2813              FLAG_TEST_STENCIL | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS | FLAG_EARLY_AND_LATE_FRAGMENT_TESTS},
2814 #endif
2815         };
2816 
2817         for (int i = 0; i < DE_LENGTH_OF_ARRAY(cases); ++i)
2818             testGroup->addChild(new EarlyFragmentDiscardTest(testCtx, cases[i].caseName, cases[i].flags));
2819     }
2820 
2821     // Check that writing to gl_SampleMask does not affect depth test writes.
2822     {
2823         static const struct
2824         {
2825             std::string caseName;
2826             uint32_t flags;
2827         } cases[] = {
2828             {"samplemask_no_early_fragment_tests_depth", FLAG_TEST_DEPTH | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS},
2829             {"samplemask_early_fragment_tests_depth", FLAG_TEST_DEPTH},
2830 #ifndef CTS_USES_VULKANSC
2831             {"samplemask_early_and_late_fragment_tests_depth_replacing_mode",
2832              FLAG_TEST_DEPTH | FLAG_EARLY_AND_LATE_FRAGMENT_TESTS | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS},
2833             {"samplemask_early_and_late_fragment_tests_depth", FLAG_TEST_DEPTH | FLAG_EARLY_AND_LATE_FRAGMENT_TESTS},
2834 #endif
2835         };
2836 
2837         const VkSampleCountFlags sampleCounts[] = {VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_8_BIT,
2838                                                    VK_SAMPLE_COUNT_16_BIT};
2839         const std::string sampleCountsStr[]     = {"samples_2", "samples_4", "samples_8", "samples_16"};
2840 
2841         for (uint32_t sampleCountsNdx = 0; sampleCountsNdx < DE_LENGTH_OF_ARRAY(sampleCounts); sampleCountsNdx++)
2842         {
2843             for (int i = 0; i < DE_LENGTH_OF_ARRAY(cases); ++i)
2844                 testGroup->addChild(
2845                     new EarlyFragmentSampleMaskTest(testCtx, cases[i].caseName + "_" + sampleCountsStr[sampleCountsNdx],
2846                                                     cases[i].flags, sampleCounts[sampleCountsNdx]));
2847         }
2848     }
2849 
2850     // We kill half of the samples at different points in the pipeline depending on early frag test, and then we verify the sample counting works as expected.
2851     {
2852         const VkSampleCountFlags sampleCounts[] = {VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_8_BIT,
2853                                                    VK_SAMPLE_COUNT_16_BIT};
2854         const std::string sampleCountsStr[]     = {"samples_2", "samples_4", "samples_8", "samples_16"};
2855 
2856         for (uint32_t sampleCountsNdx = 0; sampleCountsNdx < DE_LENGTH_OF_ARRAY(sampleCounts); sampleCountsNdx++)
2857         {
2858             SampleCountTestParams params{
2859                 sampleCounts[sampleCountsNdx], // uint32_t sampleCount;
2860                 false,                         // bool earlyAndLate;
2861                 false,                         // bool alphaToCoverage;
2862                 false,                         // bool useMaintenance5;
2863             };
2864 
2865             testGroup->addChild(new EarlyFragmentSampleCountTest(
2866                 testCtx, "sample_count_early_fragment_tests_depth_" + sampleCountsStr[sampleCountsNdx], params));
2867 #ifndef CTS_USES_VULKANSC
2868             params.earlyAndLate = true;
2869             testGroup->addChild(new EarlyFragmentSampleCountTest(
2870                 testCtx, "sample_count_early_and_late_fragment_tests_depth_" + sampleCountsStr[sampleCountsNdx],
2871                 params));
2872 
2873             params.useMaintenance5 = true;
2874             testGroup->addChild(new EarlyFragmentSampleCountTest(testCtx,
2875                                                                  "sample_count_early_and_late_fragment_tests_depth_" +
2876                                                                      sampleCountsStr[sampleCountsNdx] + "_maintenance5",
2877                                                                  params));
2878             params.earlyAndLate = false;
2879             testGroup->addChild(new EarlyFragmentSampleCountTest(testCtx,
2880                                                                  "sample_count_early_fragment_tests_depth_" +
2881                                                                      sampleCountsStr[sampleCountsNdx] + "_maintenance5",
2882                                                                  params));
2883             params.alphaToCoverage = true;
2884             testGroup->addChild(
2885                 new EarlyFragmentSampleCountTest(testCtx,
2886                                                  "sample_count_early_fragment_tests_depth_alpha_to_coverage_" +
2887                                                      sampleCountsStr[sampleCountsNdx] + "_maintenance5",
2888                                                  params));
2889 #endif
2890         }
2891     }
2892 
2893     return testGroup.release();
2894 }
2895 
2896 } // namespace FragmentOperations
2897 } // namespace vkt
2898