xref: /aosp_15_r20/external/deqp/external/vulkancts/modules/vulkan/draw/vktDrawSampleAttributeTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2022,2023 The Khronos Group Inc.
6  * Copyright (c) 2022,2023 Valve Corporation.
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 vktDrawSampleAttributeTests.cpp
22  * \brief Tests for the sample interpolation attribute
23  *//*--------------------------------------------------------------------*/
24 
25 #include "tcuStringTemplate.hpp"
26 #include "vkCmdUtil.hpp"
27 #include "vkQueryUtil.hpp"
28 #include "vkTypeUtil.hpp"
29 #include "vkQueryUtil.hpp"
30 #include "vktDrawBaseClass.hpp"
31 #include "vktTestGroupUtil.hpp"
32 #include "tcuVectorUtil.hpp"
33 
34 #include "vkPipelineConstructionUtil.hpp"
35 #include "vktTestGroupUtil.hpp"
36 
37 #include "vkDefs.hpp"
38 #include "tcuImageCompare.hpp"
39 #include "vkImageUtil.hpp"
40 #include "deStringUtil.hpp"
41 #include "vktTestCaseUtil.hpp"
42 #include "vkTypeUtil.hpp"
43 #include "vkCmdUtil.hpp"
44 #include "vkObjUtil.hpp"
45 #include "vkImageWithMemory.hpp"
46 #include "vkBarrierUtil.hpp"
47 #include "vkBufferWithMemory.hpp"
48 #include "vkBuilderUtil.hpp"
49 
50 namespace vkt
51 {
52 namespace Draw
53 {
54 namespace
55 {
56 
57 using namespace vk;
58 
59 enum class Trigger
60 {
61     SAMPLE_ID_STATIC_USE = 0,
62     SAMPLE_POSITION_STATIC_USE,
63     SAMPLE_DECORATION_DYNAMIC_USE,
64 };
65 
66 struct TestParameters
67 {
68     const SharedGroupParams general;
69 
70     // Test case variant on the fragment shader.
71     Trigger trigger;
72 };
73 
74 /*
75  * Test that sample interpolation correctly enables sample shading at a rate of 1.0
76  */
77 class SampleShadingSampleAttributeTestCase : public vkt::TestCase
78 {
79 public:
80     SampleShadingSampleAttributeTestCase(tcu::TestContext &context, const std::string &name,
81                                          const TestParameters &params);
82     void initPrograms(SourceCollections &programCollection) const override;
83     TestInstance *createInstance(Context &context) const override;
84     void checkSupport(Context &context) const override;
85 
86 private:
87     const TestParameters m_params;
88 };
89 
90 class SampleShadingSampleAttributeTestInstance : public vkt::TestInstance
91 {
92 public:
93     SampleShadingSampleAttributeTestInstance(Context &context, const TestParameters &params);
94     tcu::TestStatus iterate(void) override;
95 
96 private:
97     const TestParameters m_params;
98 
99     static constexpr uint32_t width                    = 4u;
100     static constexpr uint32_t height                   = 4u;
101     static constexpr VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_4_BIT;
102     static constexpr uint32_t expectedCounter          = sampleCount * width * height;
103 };
104 
SampleShadingSampleAttributeTestCase(tcu::TestContext & context,const std::string & name,const TestParameters & params)105 SampleShadingSampleAttributeTestCase::SampleShadingSampleAttributeTestCase(tcu::TestContext &context,
106                                                                            const std::string &name,
107                                                                            const TestParameters &params)
108     : vkt::TestCase(context, name)
109     , m_params(params)
110 {
111 }
112 
checkSupport(Context & context) const113 void SampleShadingSampleAttributeTestCase::checkSupport(Context &context) const
114 {
115     const bool declareSampleId       = (m_params.trigger == Trigger::SAMPLE_ID_STATIC_USE);
116     const bool declareSamplePosition = (m_params.trigger == Trigger::SAMPLE_POSITION_STATIC_USE);
117 
118     if (m_params.general->useDynamicRendering)
119         context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
120     context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_FRAGMENT_STORES_AND_ATOMICS);
121 
122     if (declareSampleId || declareSamplePosition)
123         context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SAMPLE_RATE_SHADING);
124 }
125 
initPrograms(SourceCollections & collection) const126 void SampleShadingSampleAttributeTestCase::initPrograms(SourceCollections &collection) const
127 {
128     const bool sampleFragInput       = (m_params.trigger == Trigger::SAMPLE_DECORATION_DYNAMIC_USE);
129     const bool declareSampleId       = (m_params.trigger == Trigger::SAMPLE_ID_STATIC_USE);
130     const bool declareSamplePosition = (m_params.trigger == Trigger::SAMPLE_POSITION_STATIC_USE);
131 
132     {
133         std::ostringstream src;
134         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
135             << "vec2 positions[3] = vec2[](\n"
136             << "    vec2(-1.0, -1.0),\n"
137             << "    vec2(3.0, -1.0),\n"
138             << "    vec2(-1.0, 3.0)\n"
139             << ");\n"
140             << (sampleFragInput ? "layout (location = 0) out float verify;\n" : "") << "void main() {\n"
141             << "    const uint triIdx     = gl_VertexIndex / 3u;\n" // In practice this will always be zero.
142             << "    const uint triVertIdx = gl_VertexIndex % 3u;\n"
143             << "    gl_Position = vec4(positions[triVertIdx], 0.0, 1.0);\n"
144             << (sampleFragInput ? "    verify = float(triIdx) + float(triVertIdx) / 16.0 + 0.75;\n" :
145                                   "") // In practice a number between 0.75 and 1.0.
146             << "}\n";
147         collection.glslSources.add("vert") << glu::VertexSource(src.str());
148     }
149 
150     {
151         std::ostringstream src;
152         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
153             << "layout (location = 0) out vec4 outColor;\n"
154             << (sampleFragInput ? "layout (location = 0) sample in float verify;\n" : "")
155             << "layout (std430, binding = 0) buffer Output {\n"
156             << "    uint invocationCount;\n"
157             << "} buf;\n"
158             << "void main() {\n"
159             << (declareSampleId ? "    gl_SampleID;\n" : "")
160             << (declareSamplePosition ? "    gl_SamplePosition;\n" : "")
161             << "    uint one   = " << (sampleFragInput ? "uint(ceil(verify))" : "1") << ";\n"
162             << "    uint index = atomicAdd(buf.invocationCount, one);\n"
163             << "    outColor = vec4(float(one), 1.0, 0.0, 1.0);\n"
164             << "}\n";
165         collection.glslSources.add("frag") << glu::FragmentSource(src.str());
166     }
167 }
168 
createInstance(Context & context) const169 TestInstance *SampleShadingSampleAttributeTestCase::createInstance(Context &context) const
170 {
171     return new SampleShadingSampleAttributeTestInstance(context, m_params);
172 }
173 
SampleShadingSampleAttributeTestInstance(Context & context,const TestParameters & params)174 SampleShadingSampleAttributeTestInstance::SampleShadingSampleAttributeTestInstance(Context &context,
175                                                                                    const TestParameters &params)
176     : vkt::TestInstance(context)
177     , m_params(params)
178 {
179 }
180 
iterate(void)181 tcu::TestStatus SampleShadingSampleAttributeTestInstance::iterate(void)
182 {
183     const auto ctx = m_context.getContextCommonData();
184 
185     // Verification buffer.
186     const auto bufferSize = static_cast<VkDeviceSize>(sizeof(uint32_t));
187     BufferWithMemory buffer(ctx.vkd, ctx.device, ctx.allocator,
188                             makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT),
189                             MemoryRequirement::HostVisible);
190     auto &bufferAlloc = buffer.getAllocation();
191     void *bufferData  = bufferAlloc.getHostPtr();
192 
193     deMemset(bufferData, 0, static_cast<size_t>(bufferSize));
194     flushAlloc(ctx.vkd, ctx.device, bufferAlloc);
195 
196     // Color attachment.
197     const auto imageFormat = VK_FORMAT_R8G8B8A8_UNORM;
198     const auto imageExtent = makeExtent3D(width, height, 1u);
199 
200     const std::vector<VkViewport> viewports{makeViewport(imageExtent)};
201     const std::vector<VkRect2D> scissors{makeRect2D(imageExtent)};
202 
203     const auto subresourceRange = makeDefaultImageSubresourceRange();
204     const auto imageUsage =
205         static_cast<VkImageUsageFlags>(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
206 
207     const VkImageCreateInfo imageCreateInfo = {
208         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
209         nullptr,                             // const void* pNext;
210         0u,                                  // VkImageCreateFlags flags;
211         VK_IMAGE_TYPE_2D,                    // VkImageType imageType;
212         imageFormat,                         // VkFormat format;
213         imageExtent,                         // VkExtent3D extent;
214         1u,                                  // uint32_t mipLevels;
215         1u,                                  // uint32_t arrayLayers;
216         sampleCount,                         // VkSampleCountFlagBits samples;
217         VK_IMAGE_TILING_OPTIMAL,             // VkImageTiling tiling;
218         imageUsage,                          // VkImageUsageFlags usage;
219         VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode sharingMode;
220         0u,                                  // uint32_t queueFamilyIndexCount;
221         nullptr,                             // const uint32_t* pQueueFamilyIndices;
222         VK_IMAGE_LAYOUT_UNDEFINED,           // VkImageLayout initialLayout;
223     };
224 
225     ImageWithMemory colorAttachment(ctx.vkd, ctx.device, ctx.allocator, imageCreateInfo, MemoryRequirement::Any);
226     const auto colorAttachmentView =
227         makeImageView(ctx.vkd, ctx.device, colorAttachment.get(), VK_IMAGE_VIEW_TYPE_2D, imageFormat, subresourceRange);
228 
229     // Structures used for renderpasses and dynamic rendering.
230     RenderPassCreateInfo renderPassCreateInfo;
231 
232     const VkAttachmentReference colorAttachmentReference = {0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL};
233 
234     renderPassCreateInfo.addAttachment(
235         AttachmentDescription(imageFormat, sampleCount, VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_STORE,
236                               VK_ATTACHMENT_LOAD_OP_DONT_CARE, VK_ATTACHMENT_STORE_OP_DONT_CARE,
237                               VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL));
238 
239     renderPassCreateInfo.addSubpass(SubpassDescription(VK_PIPELINE_BIND_POINT_GRAPHICS, 0, 0, nullptr, 1,
240                                                        &colorAttachmentReference, nullptr, AttachmentReference(), 0,
241                                                        nullptr));
242 
243     // Render pass and framebuffer.
244     const auto renderPass      = createRenderPass(ctx.vkd, ctx.device, &renderPassCreateInfo);
245     const auto framebuffer     = makeFramebuffer(ctx.vkd, ctx.device, renderPass.get(), colorAttachmentView.get(),
246                                                  imageExtent.width, imageExtent.height);
247     const auto clearValueColor = makeClearValueColor(tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
248 
249 #ifndef CTS_USES_VULKANSC
250     const VkRenderingAttachmentInfoKHR colorAttachments = {
251         VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR, // VkStructureType sType;
252         nullptr,                                         // const void* pNext;
253         colorAttachmentView.get(),                       // VkImageView imageView;
254         VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR,          // VkImageLayout imageLayout;
255         VK_RESOLVE_MODE_NONE,                            // VkResolveModeFlagBits resolveMode;
256         VK_NULL_HANDLE,                                  // VkImageView resolveImageView;
257         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,        // VkImageLayout resolveImageLayout;
258         VK_ATTACHMENT_LOAD_OP_CLEAR,                     // VkAttachmentLoadOp loadOp;
259         VK_ATTACHMENT_STORE_OP_STORE,                    // VkAttachmentStoreOp storeOp;
260         clearValueColor                                  // VkClearValue clearValue;
261     };
262 
263     const auto renderInfoFlags =
264         ((m_params.general->useDynamicRendering &&
265           !m_params.general->secondaryCmdBufferCompletelyContainsDynamicRenderpass &&
266           m_params.general->useSecondaryCmdBuffer) ?
267              static_cast<VkRenderingFlags>(VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT) :
268              0u);
269 
270     const VkRenderingInfoKHR renderInfo = {
271         VK_STRUCTURE_TYPE_RENDERING_INFO_KHR, // VkStructureType                     sType;
272         0,                                    // const void*                         pNext;
273         renderInfoFlags,                      // VkRenderingFlags                    flags;
274         scissors.at(0),                       // VkRect2D                            renderArea;
275         1,                                    // uint32_t                            layerCount;
276         0,                                    // uint32_t                            viewMask;
277         1,                                    // uint32_t                            colorAttachmentCount;
278         &colorAttachments,                    // const VkRenderingAttachmentInfo*    pColorAttachments;
279         VK_NULL_HANDLE,                       // const VkRenderingAttachmentInfo*    pDepthAttachment;
280         VK_NULL_HANDLE                        // const VkRenderingAttachmentInfo*    pStencilAttachment;
281     };
282 
283     const VkPipelineRenderingCreateInfoKHR pipelineRenderInfo = {
284         VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR, // VkStructureType    sType;
285         DE_NULL,                                              // const void*        pNext;
286         0,                                                    // uint32_t           viewMask;
287         1,                                                    // uint32_t           colorAttachmentCount;
288         &imageFormat,                                         // const VkFormat*    pColorAttachmentFormats;
289         VK_FORMAT_UNDEFINED,                                  // VkFormat           depthAttachmentFormat;
290         VK_FORMAT_UNDEFINED,                                  // VkFormat           stencilAttachmentFormat;
291     };
292     const auto *gpPNext = &pipelineRenderInfo;
293 
294     const VkCommandBufferInheritanceRenderingInfoKHR inheritanceRenderingInfo{
295         VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR, // VkStructureType sType;
296         nullptr,                                                         // const void* pNext;
297         0,                                                               // VkRenderingFlagsKHR flags;
298         0u,                                                              // uint32_t viewMask;
299         1u,                                                              // uint32_t colorAttachmentCount;
300         &imageFormat,                                                    // const VkFormat* pColorAttachmentFormats;
301         VK_FORMAT_UNDEFINED,                                             // VkFormat depthAttachmentFormat;
302         VK_FORMAT_UNDEFINED,                                             // VkFormat stencilAttachmentFormat;
303         sampleCount,                                                     // VkSampleCountFlagBits rasterizationSamples;
304     };
305 
306     const VkCommandBufferInheritanceInfo bufferInheritanceInfo{
307         VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, // VkStructureType sType;
308         &inheritanceRenderingInfo,                         // const void* pNext;
309         VK_NULL_HANDLE,                                    // VkRenderPass renderPass;
310         0u,                                                // uint32_t subpass;
311         VK_NULL_HANDLE,                                    // VkFramebuffer framebuffer;
312         VK_FALSE,                                          // VkBool32 occlusionQueryEnable;
313         (VkQueryControlFlags)0u,                           // VkQueryControlFlags queryFlags;
314         (VkQueryPipelineStatisticFlags)0u                  // VkQueryPipelineStatisticFlags pipelineStatistics;
315     };
316 #else
317     const void *gpPNext = nullptr;
318 #endif
319 
320     DescriptorSetLayoutBuilder layoutBuilder;
321     layoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT);
322 
323     const auto descriptorSetLayout    = layoutBuilder.build(ctx.vkd, ctx.device);
324     const auto graphicsPipelineLayout = makePipelineLayout(ctx.vkd, ctx.device, descriptorSetLayout.get());
325 
326     DescriptorPoolBuilder poolBuilder;
327     poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
328     const auto descriptorPool =
329         poolBuilder.build(ctx.vkd, ctx.device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
330     const auto descriptorSetBuffer =
331         makeDescriptorSet(ctx.vkd, ctx.device, descriptorPool.get(), descriptorSetLayout.get());
332 
333     // Update descriptor sets.
334     const auto bufferInfo = makeDescriptorBufferInfo(buffer.get(), 0ull, bufferSize);
335 
336     DescriptorSetUpdateBuilder updater;
337     updater.writeSingle(descriptorSetBuffer.get(), DescriptorSetUpdateBuilder::Location::binding(0u),
338                         VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &bufferInfo);
339     updater.update(ctx.vkd, ctx.device);
340 
341     const auto vtxshader = createShaderModule(ctx.vkd, ctx.device, m_context.getBinaryCollection().get("vert"));
342     const auto frgshader = createShaderModule(ctx.vkd, ctx.device, m_context.getBinaryCollection().get("frag"));
343 
344     const VkPipelineVertexInputStateCreateInfo vertexInputState = initVulkanStructure();
345 
346     // Set up a default multisample state that doesn't use sample shading and with minSampleShading set to 0.0.
347     VkPipelineMultisampleStateCreateInfo multisampling = initVulkanStructure();
348     multisampling.sampleShadingEnable                  = VK_FALSE;
349     multisampling.minSampleShading                     = 0.0;
350     multisampling.rasterizationSamples                 = sampleCount;
351 
352     const auto pass     = (m_params.general->useDynamicRendering ? VK_NULL_HANDLE : renderPass.get());
353     const auto pipeline = makeGraphicsPipeline(
354         ctx.vkd,                             // const DeviceInterface&                 vk
355         ctx.device,                          // const VkDevice                         device
356         graphicsPipelineLayout.get(),        // const VkPipelineLayout                 pipelineLayout
357         *vtxshader,                          // const VkShaderModule                   vertexShaderModule
358         VK_NULL_HANDLE,                      // const VkShaderModule                   tessellationControlModule
359         VK_NULL_HANDLE,                      // const VkShaderModule                   tessellationEvalModule
360         VK_NULL_HANDLE,                      // const VkShaderModule                   geometryShaderModule
361         *frgshader,                          // const VkShaderModule                   fragmentShaderModule
362         pass,                                // const VkRenderPass                     renderPass
363         viewports,                           // const std::vector<VkViewport>&         viewports
364         scissors,                            // const std::vector<VkRect2D>&           scissors
365         VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // const VkPrimitiveTopology              topology
366         0u,                                  // const uint32_t                         subpass
367         0u,                                  // const uint32_t                         patchControlPoints
368         &vertexInputState,                   // VkPipelineVertexInputStateCreateInfo   *vertexInputStateCreateInfo
369         VK_NULL_HANDLE,                      // VkPipelineRasterizationStateCreateInfo *rasterizationStateCreateInfo
370         &multisampling,                      // VkPipelineMultisampleStateCreateInfo   *multisampleStateCreateInfo
371         DE_NULL, // const VkPipelineDepthStencilStateCreateInfo*            depthStencilStateCreateInfo
372         DE_NULL, // const VkPipelineColorBlendStateCreateInfo*            colorBlendStateCreateInfo
373         DE_NULL, // const VkPipelineDynamicStateCreateInfo*                dynamicStateCreateInfo
374         gpPNext  // const void*                                            pNext
375     );
376 
377     const auto commandPool = createCommandPool(ctx.vkd, ctx.device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, ctx.qfIndex);
378     const auto primaryCmdBufferPtr =
379         allocateCommandBuffer(ctx.vkd, ctx.device, commandPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
380     const auto primaryCmdBuffer = *primaryCmdBufferPtr;
381 #ifndef CTS_USES_VULKANSC
382     const auto secondaryCmdBufferPtr =
383         allocateCommandBuffer(ctx.vkd, ctx.device, commandPool.get(), VK_COMMAND_BUFFER_LEVEL_SECONDARY);
384     const auto secondaryCmdBuffer = *secondaryCmdBufferPtr;
385 #endif // CTS_USES_VULKANSC
386 
387     beginCommandBuffer(ctx.vkd, primaryCmdBuffer);
388 
389     if (m_params.general->useDynamicRendering)
390     {
391 #ifndef CTS_USES_VULKANSC
392         // Transition color attachment to the proper layout.
393         const auto initialBarrier =
394             makeImageMemoryBarrier(0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
395                                    VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR, colorAttachment.get(), subresourceRange);
396         cmdPipelineImageMemoryBarrier(ctx.vkd, primaryCmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
397                                       VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, &initialBarrier);
398 
399         if (m_params.general->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
400         {
401             const VkCommandBufferUsageFlags usageFlags           = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
402             const VkCommandBufferBeginInfo commandBufBeginParams = {
403                 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
404                 nullptr,                                     // const void* pNext;
405                 usageFlags,                                  // VkCommandBufferUsageFlags flags;
406                 &bufferInheritanceInfo};
407 
408             ctx.vkd.beginCommandBuffer(secondaryCmdBuffer, &commandBufBeginParams);
409             ctx.vkd.cmdBeginRendering(secondaryCmdBuffer, &renderInfo);
410             ctx.vkd.cmdBindDescriptorSets(secondaryCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
411                                           graphicsPipelineLayout.get(), 0u, 1, &descriptorSetBuffer.get(), 0u, nullptr);
412             ctx.vkd.cmdBindPipeline(secondaryCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get());
413             ctx.vkd.cmdDraw(secondaryCmdBuffer, 3u, 1u, 0u, 0u);
414             ctx.vkd.cmdEndRendering(secondaryCmdBuffer);
415             endCommandBuffer(ctx.vkd, secondaryCmdBuffer);
416             ctx.vkd.cmdExecuteCommands(primaryCmdBuffer, 1, &secondaryCmdBuffer);
417         }
418         else if (!m_params.general->secondaryCmdBufferCompletelyContainsDynamicRenderpass &&
419                  m_params.general->useSecondaryCmdBuffer)
420         {
421             const VkCommandBufferUsageFlags usageFlags =
422                 (VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT);
423             const VkCommandBufferBeginInfo commandBufBeginParams = {
424                 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
425                 nullptr,                                     // const void* pNext;
426                 usageFlags,                                  // VkCommandBufferUsageFlags flags;
427                 &bufferInheritanceInfo};
428 
429             ctx.vkd.cmdBeginRendering(primaryCmdBuffer, &renderInfo);
430             ctx.vkd.beginCommandBuffer(secondaryCmdBuffer, &commandBufBeginParams);
431             ctx.vkd.cmdBindDescriptorSets(secondaryCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
432                                           graphicsPipelineLayout.get(), 0u, 1, &descriptorSetBuffer.get(), 0u, nullptr);
433             ctx.vkd.cmdBindPipeline(secondaryCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get());
434             ctx.vkd.cmdDraw(secondaryCmdBuffer, 3, 1, 0, 0);
435             endCommandBuffer(ctx.vkd, secondaryCmdBuffer);
436             ctx.vkd.cmdExecuteCommands(primaryCmdBuffer, 1, &secondaryCmdBuffer);
437             ctx.vkd.cmdEndRendering(primaryCmdBuffer);
438         }
439         else
440         {
441             ctx.vkd.cmdBeginRendering(primaryCmdBuffer, &renderInfo);
442             ctx.vkd.cmdBindDescriptorSets(primaryCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
443                                           graphicsPipelineLayout.get(), 0u, 1, &descriptorSetBuffer.get(), 0u, nullptr);
444             ctx.vkd.cmdBindPipeline(primaryCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get());
445             ctx.vkd.cmdDraw(primaryCmdBuffer, 3, 1, 0, 0);
446             ctx.vkd.cmdEndRendering(primaryCmdBuffer);
447         }
448 #else
449         DE_ASSERT(false);
450 #endif
451     }
452     else
453     {
454         const VkRenderPassBeginInfo renderPassBeginInfo = {
455             VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType         sType;
456             nullptr,                                  // const void*             pNext;
457             *renderPass,                              // VkRenderPass            renderPass;
458             *framebuffer,                             // VkFramebuffer           framebuffer;
459             scissors.at(0),                           // VkRect2D                renderArea;
460             1,                                        // uint32_t                clearValueCount;
461             &clearValueColor,                         // const VkClearValue*     pClearValues;
462         };
463         ctx.vkd.cmdBeginRenderPass(primaryCmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
464         ctx.vkd.cmdBindDescriptorSets(primaryCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipelineLayout.get(),
465                                       0u, 1, &descriptorSetBuffer.get(), 0u, nullptr);
466         ctx.vkd.cmdBindPipeline(primaryCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get());
467         ctx.vkd.cmdDraw(primaryCmdBuffer, 3, 1, 0, 0);
468         ctx.vkd.cmdEndRenderPass(primaryCmdBuffer);
469     }
470 
471     const VkBufferMemoryBarrier renderBufferBarrier =
472         makeBufferMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, buffer.get(), 0ull, bufferSize);
473     cmdPipelineBufferMemoryBarrier(ctx.vkd, primaryCmdBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
474                                    VK_PIPELINE_STAGE_HOST_BIT, &renderBufferBarrier);
475     endCommandBuffer(ctx.vkd, primaryCmdBuffer);
476     submitCommandsAndWait(ctx.vkd, ctx.device, m_context.getUniversalQueue(), primaryCmdBuffer);
477 
478     invalidateAlloc(ctx.vkd, ctx.device, bufferAlloc);
479 
480     uint32_t result = 0;
481     deMemcpy(&result, bufferData, sizeof(result));
482 
483     if (result < expectedCounter)
484     {
485         std::stringstream output;
486         output << "Atomic counter value lower than expected: " << result;
487         return tcu::TestStatus::fail(output.str());
488     }
489 
490     return tcu::TestStatus::pass("Pass");
491 }
492 
493 } // namespace
494 
createSampleAttributeTests(tcu::TestContext & testCtx,const SharedGroupParams groupParams)495 tcu::TestCaseGroup *createSampleAttributeTests(tcu::TestContext &testCtx, const SharedGroupParams groupParams)
496 {
497     const struct
498     {
499         Trigger trigger;
500         const char *name;
501     } triggerCases[] = {
502         // Dynamically use the sample decoration on a frag shader input variable
503         {Trigger::SAMPLE_DECORATION_DYNAMIC_USE, "sample_decoration_dynamic_use"},
504         // Declare SampleId built-in in the frag shader without using it
505         {Trigger::SAMPLE_ID_STATIC_USE, "sample_id_static_use"},
506         // Declare SamplePosition built-in in the frag shader without using it
507         {Trigger::SAMPLE_POSITION_STATIC_USE, "sample_position_static_use"},
508     };
509 
510     de::MovePtr<tcu::TestCaseGroup> group{new tcu::TestCaseGroup{testCtx, "implicit_sample_shading"}};
511 
512     for (const auto &triggerCase : triggerCases)
513     {
514         const TestParameters params{groupParams, triggerCase.trigger};
515         group->addChild(new SampleShadingSampleAttributeTestCase(testCtx, triggerCase.name, params));
516     }
517 
518     return group.release();
519 }
520 
521 } // namespace Draw
522 } // namespace vkt
523