xref: /aosp_15_r20/external/deqp/external/vulkancts/modules/vulkan/pipeline/vktPipelineMiscTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2019 Google LLC
6  * Copyright (c) 2019 The Khronos Group Inc.
7  * Copyright (c) 2023 LunarG, Inc.
8  * Copyright (c) 2023 Nintendo
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  *      http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  *
22  *//*!
23  * \file
24  * \brief Miscellaneous pipeline tests.
25  *//*--------------------------------------------------------------------*/
26 
27 #include <string>
28 #include <memory>
29 #include <vector>
30 #include <algorithm>
31 #include <array>
32 #include <numeric>
33 #include <memory>
34 
35 #include "vkPipelineConstructionUtil.hpp"
36 #include "vktAmberTestCase.hpp"
37 #include "vktPipelineMiscTests.hpp"
38 
39 #include "vkDefs.hpp"
40 #include "vkImageUtil.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 #include "vkBuilderUtil.hpp"
50 
51 #include "tcuImageCompare.hpp"
52 #include "tcuTextureUtil.hpp"
53 #include "tcuVectorUtil.hpp"
54 
55 namespace vkt
56 {
57 namespace pipeline
58 {
59 
60 using namespace vk;
61 
62 namespace
63 {
64 
65 enum AmberFeatureBits
66 {
67     AMBER_FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS = (1 << 0),
68     AMBER_FEATURE_TESSELATION_SHADER                 = (1 << 1),
69     AMBER_FEATURE_GEOMETRY_SHADER                    = (1 << 2),
70 };
71 
72 using AmberFeatureFlags = uint32_t;
73 
74 #ifndef CTS_USES_VULKANSC
getFeatureList(AmberFeatureFlags flags)75 std::vector<std::string> getFeatureList(AmberFeatureFlags flags)
76 {
77     std::vector<std::string> requirements;
78 
79     if (flags & AMBER_FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS)
80         requirements.push_back("Features.vertexPipelineStoresAndAtomics");
81 
82     if (flags & AMBER_FEATURE_TESSELATION_SHADER)
83         requirements.push_back("Features.tessellationShader");
84 
85     if (flags & AMBER_FEATURE_GEOMETRY_SHADER)
86         requirements.push_back("Features.geometryShader");
87 
88     return requirements;
89 }
90 #endif // CTS_USES_VULKANSC
91 
addMonolithicAmberTests(tcu::TestCaseGroup * tests)92 void addMonolithicAmberTests(tcu::TestCaseGroup *tests)
93 {
94 #ifndef CTS_USES_VULKANSC
95     tcu::TestContext &testCtx = tests->getTestContext();
96 
97     // Shader test files are saved in <path>/external/vulkancts/data/vulkan/amber/pipeline/<basename>.amber
98     struct Case
99     {
100         const char *basename;
101         AmberFeatureFlags flags;
102     };
103 
104     const Case cases[] = {
105         {
106             "position_to_ssbo",
107             (AMBER_FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS),
108         },
109         {
110             "primitive_id_from_tess",
111             (AMBER_FEATURE_TESSELATION_SHADER | AMBER_FEATURE_GEOMETRY_SHADER),
112         },
113         // Read gl_layer from fragment shaders without previous writes
114         {
115             "layer_read_from_frag",
116             (AMBER_FEATURE_GEOMETRY_SHADER),
117         },
118     };
119     for (unsigned i = 0; i < DE_LENGTH_OF_ARRAY(cases); ++i)
120     {
121         std::string file                      = std::string(cases[i].basename) + ".amber";
122         std::vector<std::string> requirements = getFeatureList(cases[i].flags);
123         cts_amber::AmberTestCase *testCase =
124             cts_amber::createAmberTestCase(testCtx, cases[i].basename, "pipeline", file, requirements);
125 
126         tests->addChild(testCase);
127     }
128 #else
129     DE_UNREF(tests);
130 #endif
131 }
132 
133 class ImplicitPrimitiveIDPassthroughCase : public vkt::TestCase
134 {
135 public:
ImplicitPrimitiveIDPassthroughCase(tcu::TestContext & testCtx,const std::string & name,const PipelineConstructionType pipelineConstructionType,bool withTessellation)136     ImplicitPrimitiveIDPassthroughCase(tcu::TestContext &testCtx, const std::string &name,
137                                        const PipelineConstructionType pipelineConstructionType, bool withTessellation)
138         : vkt::TestCase(testCtx, name)
139         , m_pipelineConstructionType(pipelineConstructionType)
140         , m_withTessellationPassthrough(withTessellation)
141     {
142     }
~ImplicitPrimitiveIDPassthroughCase(void)143     ~ImplicitPrimitiveIDPassthroughCase(void)
144     {
145     }
146     void initPrograms(SourceCollections &programCollection) const override;
147     void checkSupport(Context &context) const override;
148     TestInstance *createInstance(Context &context) const override;
149 
150     const PipelineConstructionType m_pipelineConstructionType;
151 
152 private:
153     bool m_withTessellationPassthrough;
154 };
155 
156 class ImplicitPrimitiveIDPassthroughInstance : public vkt::TestInstance
157 {
158 public:
ImplicitPrimitiveIDPassthroughInstance(Context & context,const PipelineConstructionType pipelineConstructionType,bool withTessellation)159     ImplicitPrimitiveIDPassthroughInstance(Context &context, const PipelineConstructionType pipelineConstructionType,
160                                            bool withTessellation)
161         : vkt::TestInstance(context)
162         , m_pipelineConstructionType(pipelineConstructionType)
163         , m_renderSize(2, 2)
164         , m_extent(makeExtent3D(m_renderSize.x(), m_renderSize.y(), 1u))
165         , m_graphicsPipeline(context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(),
166                              context.getDevice(), context.getDeviceExtensions(), pipelineConstructionType)
167         , m_withTessellationPassthrough(withTessellation)
168     {
169     }
~ImplicitPrimitiveIDPassthroughInstance(void)170     ~ImplicitPrimitiveIDPassthroughInstance(void)
171     {
172     }
173     tcu::TestStatus iterate(void) override;
174 
175 private:
176     PipelineConstructionType m_pipelineConstructionType;
177     const tcu::UVec2 m_renderSize;
178     const VkExtent3D m_extent;
179     const VkFormat m_format = VK_FORMAT_R8G8B8A8_UNORM;
180     GraphicsPipelineWrapper m_graphicsPipeline;
181     bool m_withTessellationPassthrough;
182 };
183 
createInstance(Context & context) const184 TestInstance *ImplicitPrimitiveIDPassthroughCase::createInstance(Context &context) const
185 {
186     return new ImplicitPrimitiveIDPassthroughInstance(context, m_pipelineConstructionType,
187                                                       m_withTessellationPassthrough);
188 }
189 
checkSupport(Context & context) const190 void ImplicitPrimitiveIDPassthroughCase::checkSupport(Context &context) const
191 {
192     if (m_withTessellationPassthrough)
193         context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_TESSELLATION_SHADER);
194 
195     context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
196 
197     checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(),
198                                           m_pipelineConstructionType);
199 }
200 
initPrograms(SourceCollections & sources) const201 void ImplicitPrimitiveIDPassthroughCase::initPrograms(SourceCollections &sources) const
202 {
203     std::ostringstream vert;
204     // Generate a vertically split framebuffer, filled with red on the
205     // left, and a green on the right.
206     vert << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
207          << "void main ()\n"
208          << "{\n"
209          << "    switch (gl_VertexIndex) {\n"
210          << "        case 0:\n"
211          << "            gl_Position = vec4(-3.0, -1.0, 0.0, 1.0);\n"
212          << "            break;\n"
213          << "        case 1:\n"
214          << "            gl_Position = vec4(0.0, 3.0, 0.0, 1.0);\n"
215          << "            break;\n"
216          << "        case 2:\n"
217          << "            gl_Position = vec4(0.0, -1.0, 0.0, 1.0);\n"
218          << "            break;\n"
219          << "        case 3:\n"
220          << "            gl_Position = vec4(0.0, -1.0, 0.0, 1.0);\n"
221          << "            break;\n"
222          << "        case 4:\n"
223          << "            gl_Position = vec4(3.0, -1.0, 0.0, 1.0);\n"
224          << "            break;\n"
225          << "        case 5:\n"
226          << "            gl_Position = vec4(0.0, 3.0, 0.0, 1.0);\n"
227          << "            break;\n"
228          << "    }\n"
229          << "}\n";
230     sources.glslSources.add("vert") << glu::VertexSource(vert.str());
231 
232     if (m_withTessellationPassthrough)
233     {
234         std::ostringstream tsc;
235         tsc << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
236             << "layout (vertices = 3) out;\n"
237             << "\n"
238             << "void main ()\n"
239             << "{\n"
240             << "    if (gl_InvocationID == 0) {\n"
241             << "        gl_TessLevelInner[0] = 1.0;\n"
242             << "        gl_TessLevelInner[1] = 1.0;\n"
243             << "        gl_TessLevelOuter[0] = 1.0;\n"
244             << "        gl_TessLevelOuter[1] = 1.0;\n"
245             << "        gl_TessLevelOuter[2] = 1.0;\n"
246             << "        gl_TessLevelOuter[3] = 1.0;\n"
247             << "    }\n"
248             << "    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
249             << "}\n";
250         sources.glslSources.add("tsc") << glu::TessellationControlSource(tsc.str());
251 
252         std::ostringstream tse;
253         tse << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
254             << "layout (triangles, equal_spacing, cw) in;\n"
255             << "\n"
256             << "void main ()\n"
257             << "{\n"
258             << "    gl_Position = gl_in[0].gl_Position * gl_TessCoord.x +\n"
259             << "                  gl_in[1].gl_Position * gl_TessCoord.y +\n"
260             << "                  gl_in[2].gl_Position * gl_TessCoord.z;\n"
261             << "}\n";
262         sources.glslSources.add("tse") << glu::TessellationEvaluationSource(tse.str());
263     }
264 
265     std::ostringstream frag;
266     frag << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
267          << "layout (location=0) out vec4 outColor;\n"
268          << "\n"
269          << "void main ()\n"
270          << "{\n"
271          << "    const vec4 red = vec4(1.0, 0.0, 0.0, 1.0);\n"
272          << "    const vec4 green = vec4(0.0, 1.0, 0.0, 1.0);\n"
273          << "    outColor = (gl_PrimitiveID % 2 == 0) ? red : green;\n"
274          << "}\n";
275     sources.glslSources.add("frag") << glu::FragmentSource(frag.str());
276 }
277 
iterate()278 tcu::TestStatus ImplicitPrimitiveIDPassthroughInstance::iterate()
279 {
280     const auto &vkd             = m_context.getDeviceInterface();
281     const auto device           = m_context.getDevice();
282     auto &alloc                 = m_context.getDefaultAllocator();
283     const auto qIndex           = m_context.getUniversalQueueFamilyIndex();
284     const auto queue            = m_context.getUniversalQueue();
285     const auto tcuFormat        = mapVkFormat(m_format);
286     const auto colorUsage       = (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
287     const auto verifBufferUsage = VK_BUFFER_USAGE_TRANSFER_DST_BIT;
288     const tcu::Vec4 clearColor(0.0f, 0.0f, 0.0f, 1.0f);
289 
290     // Color attachment.
291     const VkImageCreateInfo colorBufferInfo = {
292         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
293         nullptr,                             // const void* pNext;
294         0u,                                  // VkImageCreateFlags flags;
295         VK_IMAGE_TYPE_2D,                    // VkImageType imageType;
296         m_format,                            // VkFormat format;
297         m_extent,                            // VkExtent3D extent;
298         1u,                                  // uint32_t mipLevels;
299         1u,                                  // uint32_t arrayLayers;
300         VK_SAMPLE_COUNT_1_BIT,               // VkSampleCountFlagBits samples;
301         VK_IMAGE_TILING_OPTIMAL,             // VkImageTiling tiling;
302         colorUsage,                          // VkImageUsageFlags usage;
303         VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode sharingMode;
304         0u,                                  // uint32_t queueFamilyIndexCount;
305         nullptr,                             // const uint32_t* pQueueFamilyIndices;
306         VK_IMAGE_LAYOUT_UNDEFINED,           // VkImageLayout initialLayout;
307     };
308     ImageWithMemory colorBuffer(vkd, device, alloc, colorBufferInfo, MemoryRequirement::Any);
309     const auto colorSRR = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
310     const auto colorSRL = makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
311     const auto colorBufferView =
312         makeImageView(vkd, device, colorBuffer.get(), VK_IMAGE_VIEW_TYPE_2D, m_format, colorSRR);
313 
314     // Verification buffer.
315     const auto verifBufferSize =
316         static_cast<VkDeviceSize>(tcu::getPixelSize(tcuFormat)) * m_extent.width * m_extent.height;
317     const auto verifBufferInfo = makeBufferCreateInfo(verifBufferSize, verifBufferUsage);
318     BufferWithMemory verifBuffer(vkd, device, alloc, verifBufferInfo, MemoryRequirement::HostVisible);
319     auto &verifBufferAlloc = verifBuffer.getAllocation();
320 
321     // Render pass and framebuffer.
322     RenderPassWrapper renderPass(m_pipelineConstructionType, vkd, device, m_format);
323     renderPass.createFramebuffer(vkd, device, colorBuffer.get(), colorBufferView.get(), m_extent.width,
324                                  m_extent.height);
325 
326     // Shader modules.
327     const auto &binaries  = m_context.getBinaryCollection();
328     const auto vertModule = ShaderWrapper(vkd, device, binaries.get("vert"));
329     const auto fragModule = ShaderWrapper(vkd, device, binaries.get("frag"));
330     ShaderWrapper tscModule;
331     ShaderWrapper tseModule;
332 
333     if (m_withTessellationPassthrough)
334     {
335         tscModule = ShaderWrapper(vkd, device, binaries.get("tsc"));
336         tseModule = ShaderWrapper(vkd, device, binaries.get("tse"));
337     }
338 
339     // Viewports and scissors.
340     const std::vector<VkViewport> viewports(1u, makeViewport(m_extent));
341     const std::vector<VkRect2D> scissors(1u, makeRect2D(m_extent));
342 
343     const VkPipelineVertexInputStateCreateInfo vertexInputState     = initVulkanStructure();
344     const VkPipelineRasterizationStateCreateInfo rasterizationState = {
345         VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType                          sType;
346         DE_NULL,                                                    // const void*                              pNext;
347         (VkPipelineRasterizationStateCreateFlags)0,                 // VkPipelineRasterizationStateCreateFlags  flags;
348         VK_FALSE,                // VkBool32                                 depthClampEnable;
349         VK_FALSE,                // VkBool32                                 rasterizerDiscardEnable;
350         VK_POLYGON_MODE_FILL,    // VkPolygonMode polygonMode;
351         VK_CULL_MODE_NONE,       // VkCullModeFlags cullMode;
352         VK_FRONT_FACE_CLOCKWISE, // VkFrontFace frontFace;
353         VK_FALSE,                // VkBool32 depthBiasEnable;
354         0.0f,                    // float depthBiasConstantFactor;
355         0.0f,                    // float depthBiasClamp;
356         0.0f,                    // float depthBiasSlopeFactor;
357         1.0f,                    // float lineWidth;
358     };
359 
360     // Pipeline layout and graphics pipeline.
361     const PipelineLayoutWrapper pipelineLayout(m_pipelineConstructionType, vkd, device);
362 
363     const auto topology =
364         m_withTessellationPassthrough ? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST : VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
365     m_graphicsPipeline.setDefaultRasterizationState()
366         .setDefaultTopology(topology)
367         .setupVertexInputState(&vertexInputState)
368         .setDefaultDepthStencilState()
369         .setDefaultMultisampleState()
370         .setDefaultColorBlendState()
371         .setupPreRasterizationShaderState(viewports, scissors, pipelineLayout, *renderPass, 0u, vertModule,
372                                           &rasterizationState, tscModule, tseModule)
373         .setupFragmentShaderState(pipelineLayout, *renderPass, 0u, fragModule)
374         .setupFragmentOutputState(*renderPass)
375         .setMonolithicPipelineLayout(pipelineLayout)
376         .buildPipeline();
377 
378     // Command pool and buffer.
379     const auto cmdPool      = makeCommandPool(vkd, device, qIndex);
380     const auto cmdBufferPtr = allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
381     const auto cmdBuffer    = cmdBufferPtr.get();
382 
383     beginCommandBuffer(vkd, cmdBuffer);
384 
385     // Draw.
386     renderPass.begin(vkd, cmdBuffer, scissors.at(0u), clearColor);
387     m_graphicsPipeline.bind(cmdBuffer);
388     vkd.cmdDraw(cmdBuffer, 6, 1u, 0u, 0u);
389     renderPass.end(vkd, cmdBuffer);
390 
391     // Copy to verification buffer.
392     const auto copyRegion     = makeBufferImageCopy(m_extent, colorSRL);
393     const auto transfer2Host  = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
394     const auto color2Transfer = makeImageMemoryBarrier(
395         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
396         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, colorBuffer.get(), colorSRR);
397 
398     cmdPipelineImageMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
399                                   VK_PIPELINE_STAGE_TRANSFER_BIT, &color2Transfer);
400     vkd.cmdCopyImageToBuffer(cmdBuffer, colorBuffer.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, verifBuffer.get(), 1u,
401                              &copyRegion);
402     cmdPipelineMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
403                              &transfer2Host);
404 
405     endCommandBuffer(vkd, cmdBuffer);
406 
407     // Submit and validate result.
408     submitCommandsAndWait(vkd, device, queue, cmdBuffer);
409 
410     auto &log = m_context.getTestContext().getLog();
411     const tcu::IVec3 iExtent(static_cast<int>(m_extent.width), static_cast<int>(m_extent.height),
412                              static_cast<int>(m_extent.depth));
413     void *verifBufferData = verifBufferAlloc.getHostPtr();
414     const tcu::ConstPixelBufferAccess verifAccess(tcuFormat, iExtent, verifBufferData);
415     invalidateAlloc(vkd, device, verifBufferAlloc);
416 
417     const auto red   = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
418     const auto green = tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f);
419 
420     for (int x = 0; x < iExtent.x(); ++x)
421         for (int y = 0; y < iExtent.y(); ++y)
422         {
423             const auto resultColor   = verifAccess.getPixel(x, y);
424             const auto expectedColor = (x < iExtent.x() / 2) ? red : green;
425             if (resultColor != expectedColor)
426             {
427                 log << tcu::TestLog::ImageSet("Result image",
428                                               "Expect left side of framebuffer red, and right side green")
429                     << tcu::TestLog::Image("Result", "Verification buffer", verifAccess) << tcu::TestLog::EndImageSet;
430                 TCU_FAIL("Expected a vertically split framebuffer, filled with red on the left and green the right; "
431                          "see the log for the unexpected result");
432             }
433         }
434 
435     return tcu::TestStatus::pass("Pass");
436 }
437 
438 #ifndef CTS_USES_VULKANSC
439 class PipelineLibraryInterpolateAtSampleTestCase : public vkt::TestCase
440 {
441 public:
442     PipelineLibraryInterpolateAtSampleTestCase(tcu::TestContext &context, const std::string &name);
443     void initPrograms(vk::SourceCollections &programCollection) const override;
444     TestInstance *createInstance(Context &context) const override;
445     void checkSupport(Context &context) const override;
446     //there are 4 sample points, which may have a shader invocation each, each of them writes 5 values
447     //and we render a 2x2 grid.
448     static constexpr uint32_t width                    = 2;
449     static constexpr uint32_t height                   = 2;
450     static constexpr VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_4_BIT;
451     static constexpr uint32_t ResultCount              = (sampleCount + 1) * sampleCount * width * height;
452 };
453 
454 class PipelineLibraryInterpolateAtSampleTestInstance : public vkt::TestInstance
455 {
456 public:
457     PipelineLibraryInterpolateAtSampleTestInstance(Context &context);
458     void runTest(BufferWithMemory &index, BufferWithMemory &values, size_t bufferSize, PipelineConstructionType type);
459     virtual tcu::TestStatus iterate(void);
460 };
461 
PipelineLibraryInterpolateAtSampleTestCase(tcu::TestContext & context,const std::string & name)462 PipelineLibraryInterpolateAtSampleTestCase::PipelineLibraryInterpolateAtSampleTestCase(tcu::TestContext &context,
463                                                                                        const std::string &name)
464     : vkt::TestCase(context, name)
465 {
466 }
467 
checkSupport(Context & context) const468 void PipelineLibraryInterpolateAtSampleTestCase::checkSupport(Context &context) const
469 {
470     context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
471     context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_FRAGMENT_STORES_AND_ATOMICS);
472     checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(),
473                                           vk::PIPELINE_CONSTRUCTION_TYPE_FAST_LINKED_LIBRARY);
474 }
475 
initPrograms(vk::SourceCollections & collection) const476 void PipelineLibraryInterpolateAtSampleTestCase::initPrograms(vk::SourceCollections &collection) const
477 {
478     {
479         std::ostringstream src;
480         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
481             << "vec2 positions[6] = vec2[](\n"
482             << "        vec2(1.0, 1.0),"
483             << "        vec2(-1.0, 1.0),"
484             << "        vec2(-1.0, -1.0),"
485             << "        vec2(-1.0, -1.0),"
486             << "        vec2(1.0, -1.0),"
487             << "        vec2(1.0, 1.0)"
488             << ");\n"
489             << "float values[6] = {0.1, 0.2, 0.3, 0.4, 0.5, 0.6};\n"
490             << "layout (location=0) out float verify;"
491             << "void main() {\n"
492             << "        gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);\n"
493             << "        verify = values[gl_VertexIndex];\n"
494             << "}";
495         collection.glslSources.add("vert") << glu::VertexSource(src.str());
496     }
497 
498     {
499         std::ostringstream src;
500         src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
501             << "layout(location = 0) out vec4 outColor;\n"
502             << "layout (location=0) in float verify;"
503             << "layout(std430, binding = 0) buffer Index {"
504             << "    uint writeIndex;"
505             << "} index;\n"
506             << "layout(std430, binding = 1) buffer Values {"
507             << "    float num[" << PipelineLibraryInterpolateAtSampleTestCase::ResultCount << "];"
508             << "} values;\n"
509             << "void main() {\n"
510             << "    uint index = atomicAdd(index.writeIndex, 5);"
511             << "    float iSample1 = interpolateAtSample(verify, 0);\n"
512             << "    float iSample2 = interpolateAtSample(verify, 1);\n"
513             << "    float iSample3 = interpolateAtSample(verify, 2);\n"
514             << "    float iSample4 = interpolateAtSample(verify, 3);\n"
515             << "    values.num[index] = verify;"
516             << "    values.num[index + 1] = iSample1;"
517             << "    values.num[index + 2] = iSample2;"
518             << "    values.num[index + 3] = iSample3;"
519             << "    values.num[index + 4] = iSample4;"
520             << "    outColor = vec4(1.0, 1.0, 0.0, 1.0);\n"
521             << "}";
522         collection.glslSources.add("frag") << glu::FragmentSource(src.str());
523     }
524 }
525 
createInstance(Context & context) const526 TestInstance *PipelineLibraryInterpolateAtSampleTestCase::createInstance(Context &context) const
527 {
528     return new PipelineLibraryInterpolateAtSampleTestInstance(context);
529 }
530 
PipelineLibraryInterpolateAtSampleTestInstance(Context & context)531 PipelineLibraryInterpolateAtSampleTestInstance::PipelineLibraryInterpolateAtSampleTestInstance(Context &context)
532     : vkt::TestInstance(context)
533 {
534 }
535 
runTest(BufferWithMemory & index,BufferWithMemory & values,size_t bufferSize,PipelineConstructionType type)536 void PipelineLibraryInterpolateAtSampleTestInstance::runTest(BufferWithMemory &index, BufferWithMemory &values,
537                                                              size_t bufferSize, PipelineConstructionType type)
538 {
539     const auto &vki       = m_context.getInstanceInterface();
540     const auto &vkd       = m_context.getDeviceInterface();
541     const auto physDevice = m_context.getPhysicalDevice();
542     const auto device     = m_context.getDevice();
543     auto &alloc           = m_context.getDefaultAllocator();
544     auto imageFormat      = vk::VK_FORMAT_R8G8B8A8_UNORM;
545     auto imageExtent      = vk::makeExtent3D(2, 2, 1u);
546 
547     const std::vector<vk::VkViewport> viewports{makeViewport(imageExtent)};
548     const std::vector<vk::VkRect2D> scissors{makeRect2D(imageExtent)};
549 
550     de::MovePtr<vk::ImageWithMemory> colorAttachment;
551 
552     vk::GraphicsPipelineWrapper pipeline1(vki, vkd, physDevice, device, m_context.getDeviceExtensions(), type);
553     const auto qIndex = m_context.getUniversalQueueFamilyIndex();
554 
555     const auto subresourceRange = vk::makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
556     const auto imageUsage       = static_cast<vk::VkImageUsageFlags>(vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
557                                                                vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
558     const vk::VkImageCreateInfo imageCreateInfo = {
559         vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
560         nullptr,                                 // const void* pNext;
561         0u,                                      // VkImageCreateFlags flags;
562         vk::VK_IMAGE_TYPE_2D,                    // VkImageType imageType;
563         imageFormat,                             // VkFormat format;
564         imageExtent,                             // VkExtent3D extent;
565         1u,                                      // uint32_t mipLevels;
566         1u,                                      // uint32_t arrayLayers;
567         vk::VK_SAMPLE_COUNT_4_BIT,               // VkSampleCountFlagBits samples;
568         vk::VK_IMAGE_TILING_OPTIMAL,             // VkImageTiling tiling;
569         imageUsage,                              // VkImageUsageFlags usage;
570         vk::VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode sharingMode;
571         1u,                                      // uint32_t queueFamilyIndexCount;
572         &qIndex,                                 // const uint32_t* pQueueFamilyIndices;
573         vk::VK_IMAGE_LAYOUT_UNDEFINED,           // VkImageLayout initialLayout;
574     };
575 
576     colorAttachment = de::MovePtr<vk::ImageWithMemory>(
577         new vk::ImageWithMemory(vkd, device, alloc, imageCreateInfo, vk::MemoryRequirement::Any));
578     auto colorAttachmentView = vk::makeImageView(vkd, device, colorAttachment->get(), vk::VK_IMAGE_VIEW_TYPE_2D,
579                                                  imageFormat, subresourceRange);
580 
581     vk::DescriptorSetLayoutBuilder layoutBuilder;
582     layoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT);
583     layoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT);
584 
585     auto descriptorSetLayout = layoutBuilder.build(vkd, device);
586     vk::PipelineLayoutWrapper graphicsPipelineLayout(type, vkd, device, descriptorSetLayout.get());
587 
588     DescriptorPoolBuilder poolBuilder;
589     poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
590     poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
591     const auto descriptorPool = poolBuilder.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
592     const auto descriptorSetBuffer = makeDescriptorSet(vkd, device, descriptorPool.get(), descriptorSetLayout.get());
593 
594     // Update descriptor sets.
595     DescriptorSetUpdateBuilder updater;
596 
597     const auto indexBufferInfo = makeDescriptorBufferInfo(index.get(), 0ull, sizeof(uint32_t));
598     const auto valueBufferInfo = makeDescriptorBufferInfo(values.get(), 0ull, bufferSize);
599     updater.writeSingle(descriptorSetBuffer.get(), DescriptorSetUpdateBuilder::Location::binding(0u),
600                         VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &indexBufferInfo);
601     updater.writeSingle(descriptorSetBuffer.get(), DescriptorSetUpdateBuilder::Location::binding(1u),
602                         VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &valueBufferInfo);
603 
604     updater.update(vkd, device);
605 
606     auto vtxshader = ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("vert"));
607     auto frgshader = ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("frag"));
608 
609     const vk::VkPipelineVertexInputStateCreateInfo vertexInputState = {
610         vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType
611         nullptr, // const void*                                 pNext
612         0u,      // VkPipelineVertexInputStateCreateFlags       flags
613         0u,      // uint32_t                                    vertexBindingDescriptionCount
614         nullptr, // const VkVertexInputBindingDescription*      pVertexBindingDescriptions
615         0u,      // uint32_t                                    vertexAttributeDescriptionCount
616         nullptr, // const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions
617     };
618 
619     VkPipelineMultisampleStateCreateInfo multisampling = initVulkanStructure();
620     multisampling.sampleShadingEnable                  = VK_FALSE;
621     multisampling.rasterizationSamples                 = VK_SAMPLE_COUNT_4_BIT;
622     multisampling.minSampleShading                     = 1.0f;     // Optional
623     multisampling.pSampleMask                          = NULL;     // Optional
624     multisampling.alphaToCoverageEnable                = VK_FALSE; // Optional
625     multisampling.alphaToOneEnable                     = VK_FALSE; // Optional
626 
627     pipeline1.setDefaultTopology(vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
628         .setDefaultRasterizationState()
629         .setDefaultDepthStencilState()
630         .setDefaultColorBlendState()
631         .setupVertexInputState(&vertexInputState)
632         .setupPreRasterizationShaderState(viewports, scissors, graphicsPipelineLayout, DE_NULL, 0u, vtxshader)
633         .setupFragmentShaderState(graphicsPipelineLayout, DE_NULL, 0u, frgshader)
634         .setupFragmentOutputState(DE_NULL, 0u, DE_NULL, &multisampling)
635         .setMonolithicPipelineLayout(graphicsPipelineLayout)
636         .buildPipeline();
637 
638     auto commandPool   = createCommandPool(vkd, device, vk::VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, qIndex);
639     auto commandBuffer = vk::allocateCommandBuffer(vkd, device, commandPool.get(), vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY);
640 
641     const auto clearValueColor = vk::makeClearValueColor(tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
642 
643     const vk::VkRect2D renderArea = {{0u, 0u}, {imageExtent.width, imageExtent.height}};
644 
645     const vk::VkRenderingAttachmentInfoKHR colorAttachments = {
646         vk::VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR, // VkStructureType sType;
647         DE_NULL,                                             // const void* pNext;
648         colorAttachmentView.get(),                           // VkImageView imageView;
649         vk::VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR,          // VkImageLayout imageLayout;
650         vk::VK_RESOLVE_MODE_NONE,                            // VkResolveModeFlagBits resolveMode;
651         DE_NULL,                                             // VkImageView resolveImageView;
652         vk::VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR,          // VkImageLayout resolveImageLayout;
653         vk::VK_ATTACHMENT_LOAD_OP_CLEAR,                     // VkAttachmentLoadOp loadOp;
654         vk::VK_ATTACHMENT_STORE_OP_STORE,                    // VkAttachmentStoreOp storeOp;
655         clearValueColor                                      // VkClearValue clearValue;
656     };
657     const VkRenderingInfoKHR render_info = {
658         VK_STRUCTURE_TYPE_RENDERING_INFO_KHR, 0, 0, renderArea, 1, 0, 1, &colorAttachments, DE_NULL, DE_NULL};
659 
660     vk::beginCommandBuffer(vkd, commandBuffer.get());
661     vk::VkImageMemoryBarrier initialBarrier =
662         makeImageMemoryBarrier(0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
663                                VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR, (*colorAttachment).get(), subresourceRange);
664     vkd.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
665                            VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0, nullptr, 0, nullptr, 1,
666                            &initialBarrier);
667     vkd.cmdBindDescriptorSets(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipelineLayout.get(), 0u, 1,
668                               &descriptorSetBuffer.get(), 0u, nullptr);
669 
670     vkd.cmdBeginRendering(*commandBuffer, &render_info);
671     pipeline1.bind(commandBuffer.get());
672     vkd.cmdSetPatchControlPointsEXT(commandBuffer.get(), 3);
673     vkd.cmdDraw(commandBuffer.get(), 6, 1, 0, 0);
674     vkd.cmdEndRendering(*commandBuffer);
675 
676     const VkBufferMemoryBarrier indexBufferBarrier = makeBufferMemoryBarrier(
677         VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, index.get(), 0ull, sizeof(uint32_t));
678     vkd.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0,
679                            nullptr, 1, &indexBufferBarrier, 0, nullptr);
680 
681     const VkBufferMemoryBarrier valueBufferBarrier =
682         makeBufferMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, values.get(), 0ull, bufferSize);
683     vkd.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0,
684                            nullptr, 1, &valueBufferBarrier, 0, nullptr);
685 
686     vk::endCommandBuffer(vkd, commandBuffer.get());
687     vk::submitCommandsAndWait(vkd, device, m_context.getUniversalQueue(), commandBuffer.get());
688 }
689 
iterate(void)690 tcu::TestStatus PipelineLibraryInterpolateAtSampleTestInstance::iterate(void)
691 {
692     const auto &vkd   = m_context.getDeviceInterface();
693     const auto device = m_context.getDevice();
694     auto &alloc       = m_context.getDefaultAllocator();
695 
696     struct ValueBuffer
697     {
698         float values[PipelineLibraryInterpolateAtSampleTestCase::ResultCount];
699     };
700 
701     size_t resultSize = PipelineLibraryInterpolateAtSampleTestCase::ResultCount;
702 
703     const auto indexBufferSize = static_cast<VkDeviceSize>(sizeof(uint32_t));
704     const auto valueBufferSize = static_cast<VkDeviceSize>(sizeof(ValueBuffer));
705 
706     auto indexCreateInfo  = makeBufferCreateInfo(indexBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
707     auto valuesCreateInfo = makeBufferCreateInfo(valueBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
708 
709     BufferWithMemory indexBufferMonolithic(vkd, device, alloc, indexCreateInfo, MemoryRequirement::HostVisible);
710     BufferWithMemory valuesBufferMonolithic(vkd, device, alloc, valuesCreateInfo, MemoryRequirement::HostVisible);
711     BufferWithMemory indexBufferGPL(vkd, device, alloc, indexCreateInfo, MemoryRequirement::HostVisible);
712     BufferWithMemory valuesBufferGPL(vkd, device, alloc, valuesCreateInfo, MemoryRequirement::HostVisible);
713 
714     auto &indexBufferMonolithicAlloc  = indexBufferMonolithic.getAllocation();
715     auto &valuesBufferMonolithicAlloc = valuesBufferMonolithic.getAllocation();
716     auto &indexBufferGPLAlloc         = indexBufferGPL.getAllocation();
717     auto &valuesBufferGPLAlloc        = valuesBufferGPL.getAllocation();
718 
719     void *indexBufferMonolithicData  = indexBufferMonolithicAlloc.getHostPtr();
720     void *valuesBufferMonolithicData = valuesBufferMonolithicAlloc.getHostPtr();
721     void *indexBufferGPLData         = indexBufferGPLAlloc.getHostPtr();
722     void *valuesBufferGPLData        = valuesBufferGPLAlloc.getHostPtr();
723 
724     deMemset(indexBufferMonolithicData, 0, sizeof(uint32_t));
725     deMemset(valuesBufferMonolithicData, 0, sizeof(ValueBuffer));
726     deMemset(indexBufferGPLData, 0, sizeof(uint32_t));
727     deMemset(valuesBufferGPLData, 0, sizeof(ValueBuffer));
728 
729     flushAlloc(vkd, device, indexBufferMonolithicAlloc);
730     flushAlloc(vkd, device, valuesBufferMonolithicAlloc);
731     flushAlloc(vkd, device, indexBufferGPLAlloc);
732     flushAlloc(vkd, device, valuesBufferGPLAlloc);
733 
734     runTest(indexBufferMonolithic, valuesBufferMonolithic, valueBufferSize, vk::PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC);
735     runTest(indexBufferGPL, valuesBufferGPL, valueBufferSize, vk::PIPELINE_CONSTRUCTION_TYPE_FAST_LINKED_LIBRARY);
736 
737     invalidateAlloc(vkd, device, indexBufferMonolithicAlloc);
738     invalidateAlloc(vkd, device, valuesBufferMonolithicAlloc);
739     invalidateAlloc(vkd, device, indexBufferGPLAlloc);
740     invalidateAlloc(vkd, device, valuesBufferGPLAlloc);
741 
742     uint32_t monolithicIndex;
743     uint32_t GPLIndex;
744     struct ValueBuffer monolithicResult = ValueBuffer();
745     struct ValueBuffer GPLResult        = ValueBuffer();
746     memcpy((void *)&monolithicIndex, indexBufferMonolithicData, sizeof(uint32_t));
747     memcpy((void *)&GPLIndex, indexBufferGPLData, sizeof(uint32_t));
748     memcpy((void *)&monolithicResult, valuesBufferMonolithicData, sizeof(ValueBuffer));
749     memcpy((void *)&GPLResult, valuesBufferGPLData, sizeof(ValueBuffer));
750 
751     //we can't know which order the shaders will run in
752     std::sort(monolithicResult.values, monolithicResult.values + resultSize);
753     std::sort(GPLResult.values, GPLResult.values + resultSize);
754 
755     //check that the atomic counters are at enough for the number of invocations
756     constexpr int expected = (PipelineLibraryInterpolateAtSampleTestCase::sampleCount + 1) *
757                              PipelineLibraryInterpolateAtSampleTestCase::width *
758                              PipelineLibraryInterpolateAtSampleTestCase::height;
759 
760     if (monolithicIndex < expected && GPLIndex < expected)
761     {
762         return tcu::TestStatus::fail("Atomic counter value lower than expected");
763     }
764 
765     for (uint32_t i = 1; i < PipelineLibraryInterpolateAtSampleTestCase::ResultCount; i++)
766     {
767         if (monolithicResult.values[i] != monolithicResult.values[i])
768         {
769             return tcu::TestStatus::fail("Comparison failed");
770         }
771     }
772 
773     return tcu::TestStatus::pass("Pass");
774 }
775 #endif
776 
777 struct BindingTestConfig
778 {
779     PipelineConstructionType construction;
780     bool backwardsBinding;
781     bool holes;
782 };
783 
784 /*
785  * Test the following behaviours:
786  * Descriptor sets updated/bound in backwards order
787  * Descriptor sets with index holes updated/bound/used
788  */
789 class PipelineLayoutBindingTestCases : public vkt::TestCase
790 {
791 public:
PipelineLayoutBindingTestCases(tcu::TestContext & testCtx,const std::string & name,const BindingTestConfig & config)792     PipelineLayoutBindingTestCases(tcu::TestContext &testCtx, const std::string &name, const BindingTestConfig &config)
793         : vkt::TestCase(testCtx, name)
794         , m_config(config)
795     {
796     }
~PipelineLayoutBindingTestCases(void)797     ~PipelineLayoutBindingTestCases(void)
798     {
799     }
800     void initPrograms(SourceCollections &programCollection) const override;
801     void checkSupport(Context &context) const override;
802     TestInstance *createInstance(Context &context) const override;
803 
804     const BindingTestConfig m_config;
805 };
806 
807 class PipelineLayoutBindingTestInstance : public vkt::TestInstance
808 {
809 public:
PipelineLayoutBindingTestInstance(Context & context,const BindingTestConfig & config)810     PipelineLayoutBindingTestInstance(Context &context, const BindingTestConfig &config)
811         : vkt::TestInstance(context)
812         , m_renderSize(2, 2)
813         , m_extent(makeExtent3D(m_renderSize.x(), m_renderSize.y(), 1u))
814         , m_format(VK_FORMAT_R8G8B8A8_UNORM)
815         , m_graphicsPipeline(context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(),
816                              context.getDevice(), context.getDeviceExtensions(), config.construction)
817         , m_config(config)
818     {
819     }
~PipelineLayoutBindingTestInstance(void)820     ~PipelineLayoutBindingTestInstance(void)
821     {
822     }
823     tcu::TestStatus iterate(void) override;
824 
825 private:
826     const tcu::UVec2 m_renderSize;
827     const VkExtent3D m_extent;
828     const VkFormat m_format;
829     GraphicsPipelineWrapper m_graphicsPipeline;
830     const BindingTestConfig m_config;
831 };
832 
createInstance(Context & context) const833 TestInstance *PipelineLayoutBindingTestCases::createInstance(Context &context) const
834 {
835     return new PipelineLayoutBindingTestInstance(context, m_config);
836 }
837 
checkSupport(Context & context) const838 void PipelineLayoutBindingTestCases::checkSupport(Context &context) const
839 {
840     checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(),
841                                           m_config.construction);
842 }
843 
initPrograms(SourceCollections & sources) const844 void PipelineLayoutBindingTestCases::initPrograms(SourceCollections &sources) const
845 {
846     std::ostringstream src;
847     src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
848         << "vec2 positions[3] = vec2[](\n"
849         << "        vec2(-1.0, -1.0),"
850         << "        vec2(3.0, -1.0),"
851         << "        vec2(-1.0, 3.0)"
852         << ");\n"
853         << "void main() {\n"
854         << "        gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);\n"
855         << "}";
856     sources.glslSources.add("vert") << glu::VertexSource(src.str());
857 
858     std::ostringstream frag;
859     frag << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
860          << "layout (location=0) out vec4 outColor;\n"
861          << "layout(set = 0, binding = 0) uniform Output0 {"
862          << "    uint data;"
863          << "} buf0;\n";
864     if (!m_config.holes)
865     {
866         frag << "layout(set = 1, binding = 0) uniform Output1 {"
867              << "    uint data;"
868              << "} buf1;\n"
869              << "layout(set = 2, binding = 0) uniform Output2 {"
870              << "    uint data;"
871              << "} buf2;\n"
872              << "\n";
873     }
874     frag << "layout(set = 3, binding = 0) uniform Output3 {"
875          << "    uint data;"
876          << "} buf3;\n"
877          << "void main ()\n"
878          << "{\n"
879          << "    const vec4 red = vec4(1.0, 0.0, 0.0, 1.0);\n"
880          << "    const vec4 green = vec4(0.0, 1.0, 0.0, 1.0);\n";
881     if (!m_config.holes)
882     {
883         frag << "    outColor = ((buf0.data == 0) && (buf1.data == 1) && (buf2.data == 2) && (buf3.data == 3)) ? green "
884                 ": red;\n";
885     }
886     else
887     {
888         frag << "    outColor = ((buf0.data == 0) && (buf3.data == 3)) ? green : red;\n";
889     }
890     frag << "}\n";
891     sources.glslSources.add("frag") << glu::FragmentSource(frag.str());
892 }
893 
iterate()894 tcu::TestStatus PipelineLayoutBindingTestInstance::iterate()
895 {
896     const auto &vkd             = m_context.getDeviceInterface();
897     const auto device           = m_context.getDevice();
898     auto &alloc                 = m_context.getDefaultAllocator();
899     const auto qIndex           = m_context.getUniversalQueueFamilyIndex();
900     const auto queue            = m_context.getUniversalQueue();
901     const auto tcuFormat        = mapVkFormat(m_format);
902     const auto colorUsage       = (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
903     const auto verifBufferUsage = VK_BUFFER_USAGE_TRANSFER_DST_BIT;
904     const tcu::Vec4 clearColor(0.0f, 0.0f, 0.0f, 1.0f);
905 
906     // Color attachment.
907     const VkImageCreateInfo colorBufferInfo = {
908         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
909         nullptr,                             // const void* pNext;
910         0u,                                  // VkImageCreateFlags flags;
911         VK_IMAGE_TYPE_2D,                    // VkImageType imageType;
912         m_format,                            // VkFormat format;
913         m_extent,                            // VkExtent3D extent;
914         1u,                                  // uint32_t mipLevels;
915         1u,                                  // uint32_t arrayLayers;
916         VK_SAMPLE_COUNT_1_BIT,               // VkSampleCountFlagBits samples;
917         VK_IMAGE_TILING_OPTIMAL,             // VkImageTiling tiling;
918         colorUsage,                          // VkImageUsageFlags usage;
919         VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode sharingMode;
920         0u,                                  // uint32_t queueFamilyIndexCount;
921         nullptr,                             // const uint32_t* pQueueFamilyIndices;
922         VK_IMAGE_LAYOUT_UNDEFINED,           // VkImageLayout initialLayout;
923     };
924     ImageWithMemory colorBuffer(vkd, device, alloc, colorBufferInfo, MemoryRequirement::Any);
925     const auto colorSRR = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
926     const auto colorSRL = makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
927     const auto colorBufferView =
928         makeImageView(vkd, device, colorBuffer.get(), VK_IMAGE_VIEW_TYPE_2D, m_format, colorSRR);
929 
930     // Verification buffer.
931     const auto verifBufferSize =
932         static_cast<VkDeviceSize>(tcu::getPixelSize(tcuFormat)) * m_extent.width * m_extent.height;
933     const auto verifBufferInfo = makeBufferCreateInfo(verifBufferSize, verifBufferUsage);
934     BufferWithMemory verifBuffer(vkd, device, alloc, verifBufferInfo, MemoryRequirement::HostVisible);
935     auto &verifBufferAlloc = verifBuffer.getAllocation();
936 
937     // Render pass and framebuffer.
938     RenderPassWrapper renderPass(m_config.construction, vkd, device, m_format);
939     renderPass.createFramebuffer(vkd, device, colorBuffer.get(), colorBufferView.get(), m_extent.width,
940                                  m_extent.height);
941 
942     // Shader modules.
943     const auto &binaries  = m_context.getBinaryCollection();
944     const auto vertModule = ShaderWrapper(vkd, device, binaries.get("vert"));
945     const auto fragModule = ShaderWrapper(vkd, device, binaries.get("frag"));
946 
947     // Viewports and scissors.
948     const std::vector<VkViewport> viewports(1u, makeViewport(m_extent));
949     const std::vector<VkRect2D> scissors(1u, makeRect2D(m_extent));
950 
951     const VkPipelineVertexInputStateCreateInfo vertexInputState     = initVulkanStructure();
952     const VkPipelineRasterizationStateCreateInfo rasterizationState = {
953         VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType                          sType;
954         DE_NULL,                                                    // const void*                              pNext;
955         (VkPipelineRasterizationStateCreateFlags)0,                 // VkPipelineRasterizationStateCreateFlags  flags;
956         VK_FALSE,                // VkBool32                                 depthClampEnable;
957         VK_FALSE,                // VkBool32                                 rasterizerDiscardEnable;
958         VK_POLYGON_MODE_FILL,    // VkPolygonMode polygonMode;
959         VK_CULL_MODE_NONE,       // VkCullModeFlags cullMode;
960         VK_FRONT_FACE_CLOCKWISE, // VkFrontFace frontFace;
961         VK_FALSE,                // VkBool32 depthBiasEnable;
962         0.0f,                    // float depthBiasConstantFactor;
963         0.0f,                    // float depthBiasClamp;
964         0.0f,                    // float depthBiasSlopeFactor;
965         1.0f,                    // float lineWidth;
966     };
967 
968     std::array<int, 4> tmpIndices = {};
969     std::array<int, 4> indices    = {};
970     std::iota(tmpIndices.begin(), tmpIndices.end(), 0);
971     if (m_config.backwardsBinding)
972     {
973         std::copy(tmpIndices.rbegin(), tmpIndices.rend(), indices.begin());
974     }
975     else
976     {
977         std::copy(tmpIndices.begin(), tmpIndices.end(), indices.begin());
978     }
979 
980     vk::DescriptorSetLayoutBuilder layoutBuilder;
981     layoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT);
982 
983     std::vector<vk::Move<VkDescriptorSetLayout>> descriptorSetLayouts = {};
984 
985     for (size_t i = 0; i < indices.size(); i++)
986     {
987         descriptorSetLayouts.emplace_back(layoutBuilder.build(vkd, device));
988     }
989 
990     // Pipeline layout and graphics pipeline.
991     uint32_t setAndDescriptorCount = de::sizeU32(indices);
992     const vk::PipelineLayoutWrapper pipelineLayout(m_config.construction, vkd, device, descriptorSetLayouts);
993     DescriptorPoolBuilder poolBuilder;
994     poolBuilder.addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, setAndDescriptorCount);
995     const auto descriptorPool =
996         poolBuilder.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, setAndDescriptorCount);
997     std::vector<vk::Move<VkDescriptorSet>> descriptorSetsWrap = {};
998     std::vector<VkDescriptorSet> descriptorSets               = {};
999 
1000     for (const auto &setLayout : descriptorSetLayouts)
1001     {
1002         descriptorSetsWrap.emplace_back(makeDescriptorSet(vkd, device, descriptorPool.get(), setLayout.get()));
1003     }
1004 
1005     for (size_t i = 0; i < indices.size(); i++)
1006     {
1007         descriptorSets.emplace_back(descriptorSetsWrap[i].get());
1008     }
1009 
1010     const auto bufferSize = static_cast<VkDeviceSize>(sizeof(uint32_t));
1011     std::vector<std::unique_ptr<BufferWithMemory>> buffers;
1012     //create uniform buffers
1013     for (size_t i = 0; i < indices.size(); i++)
1014     {
1015         auto outBufferInfo = makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
1016         auto buffer        = std::unique_ptr<vk::BufferWithMemory>(
1017             new vk::BufferWithMemory(vkd, device, alloc, outBufferInfo, vk::MemoryRequirement::HostVisible));
1018         auto &bufferAlloc    = buffer->getAllocation();
1019         uint32_t *bufferData = (uint32_t *)bufferAlloc.getHostPtr();
1020         *bufferData          = (uint32_t)i;
1021         flushAlloc(vkd, device, bufferAlloc);
1022         buffers.push_back(std::move(buffer));
1023     }
1024 
1025     DescriptorSetUpdateBuilder updater;
1026 
1027     for (auto i : indices)
1028     {
1029         const auto bufferInfo = makeDescriptorBufferInfo(buffers[i]->get(), 0ull, bufferSize);
1030         updater.writeSingle(descriptorSets[i], DescriptorSetUpdateBuilder::Location::binding(0),
1031                             VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &bufferInfo);
1032         updater.update(vkd, device);
1033     }
1034 
1035     const auto topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
1036     m_graphicsPipeline.setDefaultRasterizationState()
1037         .setDefaultTopology(topology)
1038         .setupVertexInputState(&vertexInputState)
1039         .setDefaultDepthStencilState()
1040         .setDefaultMultisampleState()
1041         .setDefaultColorBlendState()
1042         .setupPreRasterizationShaderState(viewports, scissors, pipelineLayout, *renderPass, 0u, vertModule,
1043                                           &rasterizationState)
1044         .setupFragmentShaderState(pipelineLayout, *renderPass, 0u, fragModule)
1045         .setupFragmentOutputState(*renderPass)
1046         .setMonolithicPipelineLayout(pipelineLayout)
1047         .buildPipeline();
1048 
1049     // Command pool and buffer.
1050     const auto cmdPool      = makeCommandPool(vkd, device, qIndex);
1051     const auto cmdBufferPtr = allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1052     const auto cmdBuffer    = cmdBufferPtr.get();
1053 
1054     beginCommandBuffer(vkd, cmdBuffer);
1055 
1056     // Draw.
1057     renderPass.begin(vkd, cmdBuffer, scissors.at(0u), clearColor);
1058     for (auto i : indices)
1059     {
1060         if (m_config.holes && ((i == 1) || (i == 2)))
1061         {
1062             continue;
1063         }
1064         vkd.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), i, 1,
1065                                   &descriptorSets[i], 0u, nullptr);
1066     }
1067     m_graphicsPipeline.bind(cmdBuffer);
1068     vkd.cmdDraw(cmdBuffer, 3, 1u, 0u, 0u);
1069     renderPass.end(vkd, cmdBuffer);
1070 
1071     // Copy to verification buffer.
1072     const auto copyRegion     = makeBufferImageCopy(m_extent, colorSRL);
1073     const auto transfer2Host  = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
1074     const auto color2Transfer = makeImageMemoryBarrier(
1075         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
1076         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, colorBuffer.get(), colorSRR);
1077 
1078     cmdPipelineImageMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
1079                                   VK_PIPELINE_STAGE_TRANSFER_BIT, &color2Transfer);
1080     vkd.cmdCopyImageToBuffer(cmdBuffer, colorBuffer.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, verifBuffer.get(), 1u,
1081                              &copyRegion);
1082     cmdPipelineMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
1083                              &transfer2Host);
1084 
1085     endCommandBuffer(vkd, cmdBuffer);
1086 
1087     // Submit and validate result.
1088     submitCommandsAndWait(vkd, device, queue, cmdBuffer);
1089 
1090     const tcu::IVec3 iExtent(static_cast<int>(m_extent.width), static_cast<int>(m_extent.height),
1091                              static_cast<int>(m_extent.depth));
1092     void *verifBufferData = verifBufferAlloc.getHostPtr();
1093     const tcu::ConstPixelBufferAccess verifAccess(tcuFormat, iExtent, verifBufferData);
1094     invalidateAlloc(vkd, device, verifBufferAlloc);
1095 
1096     const auto green = tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f);
1097     tcu::TextureLevel referenceLevel(mapVkFormat(m_format), m_extent.height, m_extent.height);
1098     tcu::PixelBufferAccess reference = referenceLevel.getAccess();
1099     tcu::clear(reference, green);
1100 
1101     if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", reference,
1102                                     verifAccess, tcu::Vec4(0.0), tcu::COMPARE_LOG_ON_ERROR))
1103         return tcu::TestStatus::fail("Image comparison failed");
1104 
1105     return tcu::TestStatus::pass("Pass");
1106 }
1107 
initCompatibleRenderPassPrograms(SourceCollections & dst,PipelineConstructionType)1108 void initCompatibleRenderPassPrograms(SourceCollections &dst, PipelineConstructionType)
1109 {
1110     std::ostringstream vert;
1111     vert << "#version 460\n"
1112          << "vec2 positions[] = vec2[](\n"
1113          << "    vec2(-1.0, -1.0),\n"
1114          << "    vec2( 3.0, -1.0),\n"
1115          << "    vec2(-1.0,  3.0)\n"
1116          << ");\n"
1117          << "void main (void) {\n"
1118          << "    gl_Position = vec4(positions[gl_VertexIndex % 3], 0.0, 1.0);\n"
1119          << "}\n";
1120     dst.glslSources.add("vert") << glu::VertexSource(vert.str());
1121 
1122     std::ostringstream frag;
1123     frag << "#version 460\n"
1124          << "layout (location=0) out vec4 outColor;\n"
1125          << "void main (void) {\n"
1126          << "    outColor = vec4(0.0, 0.0, 1.0, 1.0);\n"
1127          << "}\n";
1128     dst.glslSources.add("frag") << glu::FragmentSource(frag.str());
1129 }
1130 
checkCompatibleRenderPassSupport(Context & context,PipelineConstructionType pipelineConstructionType)1131 void checkCompatibleRenderPassSupport(Context &context, PipelineConstructionType pipelineConstructionType)
1132 {
1133     const auto &vki           = context.getInstanceInterface();
1134     const auto physicalDevice = context.getPhysicalDevice();
1135 
1136     checkPipelineConstructionRequirements(vki, physicalDevice, pipelineConstructionType);
1137 }
1138 
compatibleRenderPassTest(Context & context,PipelineConstructionType pipelineConstructionType)1139 tcu::TestStatus compatibleRenderPassTest(Context &context, PipelineConstructionType pipelineConstructionType)
1140 {
1141     const auto &ctx = context.getContextCommonData();
1142     const tcu::IVec3 fbExtent(1, 1, 1);
1143     const auto vkExtent  = makeExtent3D(fbExtent);
1144     const auto fbFormat  = VK_FORMAT_R8G8B8A8_UNORM;
1145     const auto tcuFormat = mapVkFormat(fbFormat);
1146     const auto fbUsage   = (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
1147     const tcu::Vec4 clearColor(0.0f, 0.0f, 0.0f, 1.0f);
1148     const tcu::Vec4 geomColor(0.0f, 0.0f, 1.0f, 1.0f); // Must match frag shader.
1149     const tcu::Vec4 threshold(0.0f, 0.0f, 0.0f, 0.0f); // When using 0 and 1 only, we expect exact results.
1150 
1151     // Color buffer with verification buffer.
1152     ImageWithBuffer colorBuffer(ctx.vkd, ctx.device, ctx.allocator, vkExtent, fbFormat, fbUsage, VK_IMAGE_TYPE_2D);
1153 
1154     const PipelineLayoutWrapper pipelineLayout(pipelineConstructionType, ctx.vkd, ctx.device);
1155     auto renderPass         = makeRenderPass(ctx.vkd, ctx.device, fbFormat);
1156     const auto compatibleRP = makeRenderPass(ctx.vkd, ctx.device, fbFormat);
1157     const auto framebuffer =
1158         makeFramebuffer(ctx.vkd, ctx.device, *renderPass, colorBuffer.getImageView(), vkExtent.width, vkExtent.height);
1159 
1160     // Modules.
1161     const auto &binaries = context.getBinaryCollection();
1162     const ShaderWrapper vertModule(ctx.vkd, ctx.device, binaries.get("vert"));
1163     const ShaderWrapper fragModule(ctx.vkd, ctx.device, binaries.get("frag"));
1164 
1165     const std::vector<VkViewport> viewports(1u, makeViewport(vkExtent));
1166     const std::vector<VkRect2D> scissors(1u, makeRect2D(vkExtent));
1167 
1168     // Empty vertex input state.
1169     const VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo = initVulkanStructure();
1170 
1171     GraphicsPipelineWrapper pipelineWrapper(ctx.vki, ctx.vkd, ctx.physicalDevice, ctx.device,
1172                                             context.getDeviceExtensions(), pipelineConstructionType);
1173 
1174     pipelineWrapper.setDefaultTopology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
1175         .setDefaultRasterizationState()
1176         .setDefaultColorBlendState()
1177         .setDefaultMultisampleState()
1178         .setDefaultDepthStencilState()
1179         .setupVertexInputState(&vertexInputStateCreateInfo)
1180         .setupPreRasterizationShaderState(viewports, scissors, pipelineLayout, *renderPass, 0u, vertModule)
1181         .setupFragmentShaderState(pipelineLayout, *renderPass, 0u, fragModule)
1182         .setupFragmentOutputState(*renderPass);
1183 
1184     // Important: at this point, the 4 libraries should have been created. Now we destroy the original render pass to make sure it's
1185     // no longer used, and use the compatible one for the remainder of the test.
1186     renderPass = Move<VkRenderPass>();
1187 
1188     // Finally, we link the complete pipeline and use the compatible render pass in the command buffer.
1189     DE_ASSERT(isConstructionTypeLibrary(pipelineConstructionType));
1190     pipelineWrapper.setMonolithicPipelineLayout(pipelineLayout).buildPipeline();
1191 
1192     CommandPoolWithBuffer cmd(ctx.vkd, ctx.device, ctx.qfIndex);
1193     const auto cmdBuffer = *cmd.cmdBuffer;
1194 
1195     beginCommandBuffer(ctx.vkd, cmdBuffer);
1196     beginRenderPass(ctx.vkd, cmdBuffer, *compatibleRP, *framebuffer, scissors.at(0u), clearColor);
1197     pipelineWrapper.bind(cmdBuffer);
1198     ctx.vkd.cmdDraw(cmdBuffer, 3u, 1u, 0u, 0u);
1199     endRenderPass(ctx.vkd, cmdBuffer);
1200     copyImageToBuffer(ctx.vkd, cmdBuffer, colorBuffer.getImage(), colorBuffer.getBuffer(), fbExtent.swizzle(0, 1),
1201                       VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 1u,
1202                       VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_ASPECT_COLOR_BIT,
1203                       VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
1204     endCommandBuffer(ctx.vkd, cmdBuffer);
1205     submitCommandsAndWait(ctx.vkd, ctx.device, ctx.queue, cmdBuffer);
1206 
1207     // Verify color output.
1208     invalidateAlloc(ctx.vkd, ctx.device, colorBuffer.getBufferAllocation());
1209     tcu::PixelBufferAccess resultAccess(tcuFormat, fbExtent, colorBuffer.getBufferAllocation().getHostPtr());
1210 
1211     tcu::TextureLevel referenceLevel(tcuFormat, fbExtent.x(), fbExtent.y());
1212     auto referenceAccess = referenceLevel.getAccess();
1213     tcu::clear(referenceAccess, geomColor);
1214 
1215     auto &log = context.getTestContext().getLog();
1216     if (!tcu::floatThresholdCompare(log, "Result", "", referenceAccess, resultAccess, threshold,
1217                                     tcu::COMPARE_LOG_ON_ERROR))
1218         return tcu::TestStatus::fail("Unexpected color in result buffer; check log for details");
1219 
1220     return tcu::TestStatus::pass("Pass");
1221 }
1222 
1223 #ifndef CTS_USES_VULKANSC
1224 struct VaryingSamplesFragParams
1225 {
1226     const PipelineConstructionType constructionType;
1227     const VkSampleCountFlagBits multiSampleCount;
1228 };
1229 
initVaryingSamplesFragPrograms(SourceCollections & dst,VaryingSamplesFragParams)1230 void initVaryingSamplesFragPrograms(SourceCollections &dst, VaryingSamplesFragParams)
1231 {
1232     // The framebuffer will contain a single pixel and we will draw a quad using the 4 pixel corners. inSamplePos will contain 0s
1233     // and 1s in the X and Y values so that the value at each corner will match its corresponding sample location. The result is
1234     // that interpolating outSamplePos for a sample will give you the corresponding standard sample location.
1235     std::ostringstream vert;
1236     vert << "#version 460\n"
1237          << "layout (location=0) in vec4 inPos;\n"
1238          << "layout (location=1) in vec4 inSamplePos;\n"
1239          << "layout (location=0) out vec2 outSamplePos;\n"
1240          << "void main (void) {\n"
1241          << "    gl_Position = inPos;\n"
1242          << "    outSamplePos = inSamplePos.xy;\n"
1243          << "}\n";
1244     dst.glslSources.add("vert") << glu::VertexSource(vert.str());
1245 
1246     // Each frag shader invocation will interpolate the sample position for every sample, and will store the results of every
1247     // interpolation in the positions buffer. So if we work with 4 samples but get 2 actual invocations (e.g.):
1248     // - sampleCount from the push constants will be 4.
1249     // - mySampleId will end up containing 2.
1250     // - samplePositions will have 2 blocks of 4 results each, with the 4 interpolations for the first and second invocations.
1251     std::ostringstream frag;
1252     frag << "#version 460\n"
1253          << "layout (location=0) in vec2 inSamplePos;\n"
1254          << "layout (push_constant, std430) uniform PushConstantBlock { int sampleCount; } pc;\n"
1255          << "layout (set=0, binding=0, std430) buffer MySampleIdBlock { int mySampleId; } atomicBuffer;\n"
1256          << "layout (set=0, binding=1, std430) buffer SamplePositionsBlock { vec2 samplePositions[]; } "
1257             "positionsBuffer;\n"
1258          << "void main (void) {\n"
1259          << "    const int sampleId = atomicAdd(atomicBuffer.mySampleId, 1);\n"
1260          << "    memoryBarrier();\n"
1261          << "    const int bufferOffset = pc.sampleCount * sampleId;\n"
1262          << "    for (int idx = 0; idx < pc.sampleCount; ++idx) {\n"
1263          << "        positionsBuffer.samplePositions[bufferOffset + idx] = interpolateAtSample(inSamplePos, idx);\n"
1264          << "    }\n"
1265          << "}\n";
1266     dst.glslSources.add("frag") << glu::FragmentSource(frag.str());
1267 }
1268 
checkVaryingSamplesFragSupport(Context & context,VaryingSamplesFragParams params)1269 void checkVaryingSamplesFragSupport(Context &context, VaryingSamplesFragParams params)
1270 {
1271     const auto ctx = context.getContextCommonData();
1272 
1273     checkPipelineConstructionRequirements(ctx.vki, ctx.physicalDevice, params.constructionType);
1274     context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_FRAGMENT_STORES_AND_ATOMICS);
1275     context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
1276 
1277     // Check sample count support.
1278     const auto allowedSampleCounts = context.getDeviceProperties().limits.framebufferNoAttachmentsSampleCounts;
1279     if ((allowedSampleCounts & params.multiSampleCount) == 0u)
1280         TCU_THROW(NotSupportedError, "Requested sample count not supported");
1281 
1282     // Check for standard sample locations.
1283     if (!context.getDeviceProperties().limits.standardSampleLocations)
1284         TCU_THROW(NotSupportedError, "Standard sample locations required");
1285 }
1286 
1287 // This test creates a fragment shader pipeline library using a fragment shader that doesn't have sample shading enabled. In
1288 // addition, thanks to using dynamic rendering, no multisample information is included when creating such library. Then, the library
1289 // is included in two final pipelines: in one of them the multisample information indicates single-sample and, in the other one, it
1290 // indicates multisample.
1291 //
1292 // Then, the test runs two render loops: one for the single-sample pipeline and one for the multisample one. We expect that the
1293 // fragment shader produces the right results in both cases, even if the amount of samples was not available when the fragment
1294 // shader pipeline library was created.
1295 //
1296 // The fragment shader has been written in a way such that, when used with a single-pixel framebuffer, each invocation writes the
1297 // pixel locations of all available samples to an output buffer (note: so if 4 samples result in 4 invocations, we end up with a
1298 // maximum of 16 sample locations in the buffer). See the frag shader above.
varyingSamplesFragTest(Context & context,VaryingSamplesFragParams params)1299 tcu::TestStatus varyingSamplesFragTest(Context &context, VaryingSamplesFragParams params)
1300 {
1301     const auto &ctx = context.getContextCommonData();
1302     const tcu::IVec3 fbExtent(1, 1, 1);
1303     const auto &vkExtent    = makeExtent3D(fbExtent);
1304     const auto descType     = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
1305     const auto bindPoint    = VK_PIPELINE_BIND_POINT_GRAPHICS;
1306     const auto dataStages   = VK_SHADER_STAGE_FRAGMENT_BIT;
1307     const auto kBufferCount = 2u; // Matches frag shader: atomic buffer and positions buffer.
1308     const bool isOptimized  = (params.constructionType == PIPELINE_CONSTRUCTION_TYPE_LINK_TIME_OPTIMIZED_LIBRARY);
1309 
1310     struct PositionSampleCoords
1311     {
1312         const tcu::Vec4 position;
1313         const tcu::Vec4 sampleCoords;
1314     };
1315 
1316     // Vertices.
1317     const std::vector<PositionSampleCoords> vertices{
1318         PositionSampleCoords{tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f)},
1319         PositionSampleCoords{tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f), tcu::Vec4(0.0f, 1.0f, 0.0f, 0.0f)},
1320         PositionSampleCoords{tcu::Vec4(1.0f, -1.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f)},
1321         PositionSampleCoords{tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f)},
1322     };
1323 
1324     // Vertex buffer
1325     const auto vbSize = static_cast<VkDeviceSize>(de::dataSize(vertices));
1326     const auto vbInfo = makeBufferCreateInfo(vbSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
1327     BufferWithMemory vertexBuffer(ctx.vkd, ctx.device, ctx.allocator, vbInfo, MemoryRequirement::HostVisible);
1328     const auto vbAlloc  = vertexBuffer.getAllocation();
1329     void *vbData        = vbAlloc.getHostPtr();
1330     const auto vbOffset = static_cast<VkDeviceSize>(0);
1331 
1332     deMemcpy(vbData, de::dataOrNull(vertices), de::dataSize(vertices));
1333     flushAlloc(ctx.vkd, ctx.device, vbAlloc); // strictly speaking, not needed.
1334 
1335     // Storage buffers used in the fragment shader: atomic buffer and positions buffer.
1336     int32_t invocationCount = 0;
1337     const auto abSize       = static_cast<VkDeviceSize>(sizeof(invocationCount));
1338     const auto abInfo       = makeBufferCreateInfo(abSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
1339     BufferWithMemory atomicBuffer(ctx.vkd, ctx.device, ctx.allocator, abInfo, MemoryRequirement::HostVisible);
1340     const auto abAlloc  = atomicBuffer.getAllocation();
1341     void *abData        = abAlloc.getHostPtr();
1342     const auto abOffset = static_cast<VkDeviceSize>(0);
1343 
1344     const auto maxPositions = params.multiSampleCount * params.multiSampleCount;
1345     std::vector<tcu::Vec2> samplePositions(maxPositions, tcu::Vec2(-1.0f, -1.0f));
1346     const auto pbSize = static_cast<VkDeviceSize>(de::dataSize(samplePositions));
1347     const auto pbInfo = makeBufferCreateInfo(pbSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
1348     BufferWithMemory positionsBuffer(ctx.vkd, ctx.device, ctx.allocator, pbInfo, MemoryRequirement::HostVisible);
1349     const auto pbAlloc  = positionsBuffer.getAllocation();
1350     void *pbData        = pbAlloc.getHostPtr();
1351     const auto pbOffset = static_cast<VkDeviceSize>(0);
1352 
1353     // Descriptor pool, set, layout, etc.
1354     DescriptorPoolBuilder poolBuilder;
1355     poolBuilder.addType(descType, kBufferCount);
1356     const auto descriptorPool =
1357         poolBuilder.build(ctx.vkd, ctx.device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1358 
1359     DescriptorSetLayoutBuilder layoutBuilder;
1360     for (uint32_t i = 0u; i < kBufferCount; ++i)
1361         layoutBuilder.addSingleBinding(descType, dataStages);
1362     const auto setLayout     = layoutBuilder.build(ctx.vkd, ctx.device);
1363     const auto descriptorSet = makeDescriptorSet(ctx.vkd, ctx.device, *descriptorPool, *setLayout);
1364 
1365     DescriptorSetUpdateBuilder updateBuilder;
1366     const auto abDescInfo = makeDescriptorBufferInfo(atomicBuffer.get(), abOffset, abSize);
1367     const auto pbDescInfo = makeDescriptorBufferInfo(positionsBuffer.get(), pbOffset, pbSize);
1368     updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), descType, &abDescInfo);
1369     updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), descType, &pbDescInfo);
1370     updateBuilder.update(ctx.vkd, ctx.device);
1371 
1372     // Push constants.
1373     const auto pcSize  = static_cast<uint32_t>(sizeof(int32_t));
1374     const auto pcRange = makePushConstantRange(dataStages, 0u, pcSize);
1375 
1376     // Pipeline layout.
1377     const auto pipelineLayout = makePipelineLayout(ctx.vkd, ctx.device, *setLayout, &pcRange);
1378 
1379     // Modules.
1380     const auto &binaries  = context.getBinaryCollection();
1381     const auto vertModule = createShaderModule(ctx.vkd, ctx.device, binaries.get("vert"));
1382     const auto fragModule = createShaderModule(ctx.vkd, ctx.device, binaries.get("frag"));
1383 
1384     const std::vector<VkViewport> viewports(1u, makeViewport(vkExtent));
1385     const std::vector<VkRect2D> scissors(1u, makeRect2D(vkExtent));
1386 
1387     // Pipeline state.
1388 
1389     const auto bindingDesc = makeVertexInputBindingDescription(0u, static_cast<uint32_t>(sizeof(PositionSampleCoords)),
1390                                                                VK_VERTEX_INPUT_RATE_VERTEX);
1391 
1392     const std::vector<VkVertexInputAttributeDescription> inputAttributes{
1393         makeVertexInputAttributeDescription(0u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT,
1394                                             static_cast<uint32_t>(offsetof(PositionSampleCoords, position))),
1395         makeVertexInputAttributeDescription(1u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT,
1396                                             static_cast<uint32_t>(offsetof(PositionSampleCoords, sampleCoords))),
1397     };
1398 
1399     const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo = {
1400         VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
1401         nullptr,                                                   // const void* pNext;
1402         0u,                                                        // VkPipelineVertexInputStateCreateFlags flags;
1403         1u,                                                        // uint32_t vertexBindingDescriptionCount;
1404         &bindingDesc,                    // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
1405         de::sizeU32(inputAttributes),    // uint32_t vertexAttributeDescriptionCount;
1406         de::dataOrNull(inputAttributes), // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
1407     };
1408 
1409     const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateInfo = {
1410         VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
1411         nullptr,                                                     // const void* pNext;
1412         0u,                                                          // VkPipelineInputAssemblyStateCreateFlags flags;
1413         VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,                        // VkPrimitiveTopology topology;
1414         VK_FALSE,                                                    // VkBool32 primitiveRestartEnable;
1415     };
1416 
1417     const VkPipelineViewportStateCreateInfo viewportStateInfo = {
1418         VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
1419         nullptr,                                               // const void* pNext;
1420         0u,                                                    // VkPipelineViewportStateCreateFlags flags;
1421         de::sizeU32(viewports),                                // uint32_t viewportCount;
1422         de::dataOrNull(viewports),                             // const VkViewport* pViewports;
1423         de::sizeU32(scissors),                                 // uint32_t scissorCount;
1424         de::dataOrNull(scissors),                              // const VkRect2D* pScissors;
1425     };
1426 
1427     const VkPipelineRasterizationStateCreateInfo rasterizationStateInfo = {
1428         VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
1429         nullptr,                                                    // const void* pNext;
1430         0u,                                                         // VkPipelineRasterizationStateCreateFlags flags;
1431         VK_FALSE,                                                   // VkBool32 depthClampEnable;
1432         VK_FALSE,                                                   // VkBool32 rasterizerDiscardEnable;
1433         VK_POLYGON_MODE_FILL,                                       // VkPolygonMode polygonMode;
1434         VK_CULL_MODE_BACK_BIT,                                      // VkCullModeFlags cullMode;
1435         VK_FRONT_FACE_COUNTER_CLOCKWISE,                            // VkFrontFace frontFace;
1436         VK_FALSE,                                                   // VkBool32 depthBiasEnable;
1437         0.0f,                                                       // float depthBiasConstantFactor;
1438         0.0f,                                                       // float depthBiasClamp;
1439         0.0f,                                                       // float depthBiasSlopeFactor;
1440         1.0f,                                                       // float lineWidth;
1441     };
1442 
1443     // We will use two pipelines: one will be single-sample and the other one will be multisample.
1444     VkPipelineMultisampleStateCreateInfo multisampleStateInfo = {
1445         VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
1446         nullptr,                                                  // const void* pNext;
1447         0u,                                                       // VkPipelineMultisampleStateCreateFlags flags;
1448         params.multiSampleCount,                                  // VkSampleCountFlagBits rasterizationSamples;
1449         VK_FALSE,                                                 // VkBool32 sampleShadingEnable;
1450         1.0f,                                                     // float minSampleShading;
1451         nullptr,                                                  // const VkSampleMask* pSampleMask;
1452         VK_FALSE,                                                 // VkBool32 alphaToCoverageEnable;
1453         VK_FALSE,                                                 // VkBool32 alphaToOneEnable;
1454     };
1455 
1456     const VkPipelineDepthStencilStateCreateInfo depthStencilStateInfo = initVulkanStructure();
1457 
1458     const VkPipelineColorBlendStateCreateInfo colorBlendStateInfo = initVulkanStructure();
1459 
1460     const VkPipelineRenderingCreateInfo renderingCreateInfo = {
1461         VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO, // VkStructureType sType;
1462         nullptr,                                          // const void* pNext;
1463         0u,                                               // uint32_t viewMask;
1464         0u,                                               // uint32_t colorAttachmentCount;
1465         nullptr,                                          // const VkFormat* pColorAttachmentFormats;
1466         VK_FORMAT_UNDEFINED,                              // VkFormat depthAttachmentFormat;
1467         VK_FORMAT_UNDEFINED,                              // VkFormat stencilAttachmentFormat;
1468     };
1469 
1470     // Create a library with the vertex input state and the pre-rasterization shader state.
1471     Move<VkPipeline> preFragLib;
1472     Move<VkPipeline> fragShaderLib;
1473     Move<VkPipeline> fragOutputLibMulti;
1474     Move<VkPipeline> fragOutputLibSingle;
1475 
1476     VkPipelineCreateFlags libCreationFlags = VK_PIPELINE_CREATE_LIBRARY_BIT_KHR;
1477     VkPipelineCreateFlags linkFlags        = 0u;
1478 
1479     if (isOptimized)
1480     {
1481         libCreationFlags |= VK_PIPELINE_CREATE_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT;
1482         linkFlags |= VK_PIPELINE_CREATE_LINK_TIME_OPTIMIZATION_BIT_EXT;
1483     }
1484 
1485     // Vertex input state and pre-rasterization shader state library.
1486     {
1487         VkGraphicsPipelineLibraryCreateInfoEXT vertexInputLibInfo = initVulkanStructureConst(&renderingCreateInfo);
1488         vertexInputLibInfo.flags |= (VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT |
1489                                      VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT);
1490 
1491         VkGraphicsPipelineCreateInfo preFragPipelineInfo = initVulkanStructure(&vertexInputLibInfo);
1492         preFragPipelineInfo.flags                        = libCreationFlags;
1493         preFragPipelineInfo.pVertexInputState            = &vertexInputStateInfo;
1494         preFragPipelineInfo.pInputAssemblyState          = &inputAssemblyStateInfo;
1495 
1496         preFragPipelineInfo.layout              = pipelineLayout.get();
1497         preFragPipelineInfo.pViewportState      = &viewportStateInfo;
1498         preFragPipelineInfo.pRasterizationState = &rasterizationStateInfo;
1499 
1500         const auto vertexStageInfo = makePipelineShaderStageCreateInfo(VK_SHADER_STAGE_VERTEX_BIT, vertModule.get());
1501 
1502         preFragPipelineInfo.stageCount = 1u;
1503         preFragPipelineInfo.pStages    = &vertexStageInfo;
1504 
1505         preFragLib = createGraphicsPipeline(ctx.vkd, ctx.device, VK_NULL_HANDLE, &preFragPipelineInfo);
1506     }
1507 
1508     // Fragment shader stage library. Note we skip including multisample information here.
1509     {
1510         VkGraphicsPipelineLibraryCreateInfoEXT fragShaderLibInfo = initVulkanStructureConst(&renderingCreateInfo);
1511         fragShaderLibInfo.flags |= VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT;
1512 
1513         VkGraphicsPipelineCreateInfo fragShaderPipelineInfo = initVulkanStructure(&fragShaderLibInfo);
1514         fragShaderPipelineInfo.flags                        = libCreationFlags;
1515         fragShaderPipelineInfo.layout                       = pipelineLayout.get();
1516         fragShaderPipelineInfo.pDepthStencilState           = &depthStencilStateInfo;
1517 
1518         const auto fragStageInfo = makePipelineShaderStageCreateInfo(VK_SHADER_STAGE_FRAGMENT_BIT, fragModule.get());
1519 
1520         fragShaderPipelineInfo.stageCount = 1u;
1521         fragShaderPipelineInfo.pStages    = &fragStageInfo;
1522 
1523         fragShaderLib = createGraphicsPipeline(ctx.vkd, ctx.device, VK_NULL_HANDLE, &fragShaderPipelineInfo);
1524     }
1525 
1526     // Fragment output libraries.
1527     {
1528         VkGraphicsPipelineLibraryCreateInfoEXT fragOutputLibInfo = initVulkanStructureConst(&renderingCreateInfo);
1529         fragOutputLibInfo.flags |= VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT;
1530 
1531         VkGraphicsPipelineCreateInfo fragOutputPipelineInfo = initVulkanStructure(&fragOutputLibInfo);
1532         fragOutputPipelineInfo.flags                        = libCreationFlags;
1533         fragOutputPipelineInfo.pColorBlendState             = &colorBlendStateInfo;
1534         fragOutputPipelineInfo.pMultisampleState            = &multisampleStateInfo;
1535 
1536         fragOutputLibMulti = createGraphicsPipeline(ctx.vkd, ctx.device, VK_NULL_HANDLE, &fragOutputPipelineInfo);
1537 
1538         multisampleStateInfo.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
1539         fragOutputLibSingle = createGraphicsPipeline(ctx.vkd, ctx.device, VK_NULL_HANDLE, &fragOutputPipelineInfo);
1540     }
1541 
1542     // Linked pipelines.
1543     Move<VkPipeline> pipelineMulti;
1544     Move<VkPipeline> pipelineSingle;
1545 
1546     {
1547         const std::vector<VkPipeline> libraryHandlesMulti{
1548             preFragLib.get(),
1549             fragShaderLib.get(),
1550             fragOutputLibMulti.get(),
1551         };
1552 
1553         VkPipelineLibraryCreateInfoKHR linkedPipelineLibraryInfo = initVulkanStructure();
1554         linkedPipelineLibraryInfo.libraryCount                   = de::sizeU32(libraryHandlesMulti);
1555         linkedPipelineLibraryInfo.pLibraries                     = de::dataOrNull(libraryHandlesMulti);
1556 
1557         VkGraphicsPipelineCreateInfo linkedPipelineInfo = initVulkanStructure(&linkedPipelineLibraryInfo);
1558         linkedPipelineInfo.flags                        = linkFlags;
1559         linkedPipelineInfo.layout                       = pipelineLayout.get();
1560 
1561         pipelineMulti = createGraphicsPipeline(ctx.vkd, ctx.device, VK_NULL_HANDLE, &linkedPipelineInfo);
1562     }
1563     {
1564         const std::vector<VkPipeline> libraryHandlesSingle{
1565             preFragLib.get(),
1566             fragShaderLib.get(),
1567             fragOutputLibSingle.get(),
1568         };
1569 
1570         VkPipelineLibraryCreateInfoKHR linkedPipelineLibraryInfo = initVulkanStructure();
1571         linkedPipelineLibraryInfo.libraryCount                   = de::sizeU32(libraryHandlesSingle);
1572         linkedPipelineLibraryInfo.pLibraries                     = de::dataOrNull(libraryHandlesSingle);
1573 
1574         VkGraphicsPipelineCreateInfo linkedPipelineInfo = initVulkanStructure(&linkedPipelineLibraryInfo);
1575         linkedPipelineInfo.flags                        = linkFlags;
1576         linkedPipelineInfo.layout                       = pipelineLayout.get();
1577 
1578         pipelineSingle = createGraphicsPipeline(ctx.vkd, ctx.device, VK_NULL_HANDLE, &linkedPipelineInfo);
1579     }
1580 
1581     // Standard sample locations
1582     using LocationsVec = std::vector<tcu::Vec2>;
1583 
1584     const LocationsVec locationSamples1{
1585         tcu::Vec2(0.5f, 0.5f),
1586     };
1587 
1588     const LocationsVec locationSamples2{
1589         tcu::Vec2(0.75f, 0.75f),
1590         tcu::Vec2(0.25f, 0.25f),
1591     };
1592 
1593     const LocationsVec locationSamples4{
1594         tcu::Vec2(0.375f, 0.125f),
1595         tcu::Vec2(0.875f, 0.375f),
1596         tcu::Vec2(0.125f, 0.625f),
1597         tcu::Vec2(0.625f, 0.875f),
1598     };
1599 
1600     const LocationsVec locationSamples8{
1601         tcu::Vec2(0.5625f, 0.3125f), tcu::Vec2(0.4375f, 0.6875f), tcu::Vec2(0.8125f, 0.5625f),
1602         tcu::Vec2(0.3125f, 0.1875f), tcu::Vec2(0.1875f, 0.8125f), tcu::Vec2(0.0625f, 0.4375f),
1603         tcu::Vec2(0.6875f, 0.9375f), tcu::Vec2(0.9375f, 0.0625f),
1604     };
1605 
1606     const LocationsVec locationSamples16{
1607         tcu::Vec2(0.5625f, 0.5625f), tcu::Vec2(0.4375f, 0.3125f), tcu::Vec2(0.3125f, 0.625f),
1608         tcu::Vec2(0.75f, 0.4375f),   tcu::Vec2(0.1875f, 0.375f),  tcu::Vec2(0.625f, 0.8125f),
1609         tcu::Vec2(0.8125f, 0.6875f), tcu::Vec2(0.6875f, 0.1875f), tcu::Vec2(0.375f, 0.875f),
1610         tcu::Vec2(0.5f, 0.0625f),    tcu::Vec2(0.25f, 0.125f),    tcu::Vec2(0.125f, 0.75f),
1611         tcu::Vec2(0.0f, 0.5f),       tcu::Vec2(0.9375f, 0.25f),   tcu::Vec2(0.875f, 0.9375f),
1612         tcu::Vec2(0.0625f, 0.0f),
1613     };
1614 
1615     const auto locationThreshold = 0.00001f;
1616 
1617     const std::map<VkSampleCountFlagBits, const LocationsVec *> locationsByCount{
1618         std::make_pair(VK_SAMPLE_COUNT_1_BIT, &locationSamples1),
1619         std::make_pair(VK_SAMPLE_COUNT_2_BIT, &locationSamples2),
1620         std::make_pair(VK_SAMPLE_COUNT_4_BIT, &locationSamples4),
1621         std::make_pair(VK_SAMPLE_COUNT_8_BIT, &locationSamples8),
1622         std::make_pair(VK_SAMPLE_COUNT_16_BIT, &locationSamples16),
1623     };
1624 
1625     const VkRenderingInfo renderingInfo = {
1626         VK_STRUCTURE_TYPE_RENDERING_INFO, // VkStructureType sType;
1627         nullptr,                          // const void* pNext;
1628         0u,                               // VkRenderingFlags flags;
1629         scissors.at(0u),                  // VkRect2D renderArea;
1630         1u,                               // uint32_t layerCount;
1631         0u,                               // uint32_t viewMask;
1632         0u,                               // uint32_t colorAttachmentCount;
1633         nullptr,                          // const VkRenderingAttachmentInfo* pColorAttachments;
1634         nullptr,                          // const VkRenderingAttachmentInfo* pDepthAttachment;
1635         nullptr,                          // const VkRenderingAttachmentInfo* pStencilAttachment;
1636     };
1637 
1638     const auto hostToFragBarrier =
1639         makeMemoryBarrier(VK_ACCESS_HOST_WRITE_BIT, (VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT));
1640     const auto fragToHostBarrier = makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
1641 
1642     for (const auto multiSample : {false, true})
1643     {
1644         // Reset data in buffers.
1645         invocationCount = 0;
1646         deMemset(de::dataOrNull(samplePositions), 0, de::dataSize(samplePositions));
1647 
1648         deMemcpy(abData, &invocationCount, sizeof(invocationCount));
1649         flushAlloc(ctx.vkd, ctx.device, abAlloc);
1650 
1651         deMemcpy(pbData, de::dataOrNull(samplePositions), de::dataSize(samplePositions));
1652         flushAlloc(ctx.vkd, ctx.device, pbAlloc);
1653 
1654         CommandPoolWithBuffer cmd(ctx.vkd, ctx.device, ctx.qfIndex);
1655         const auto cmdBuffer = *cmd.cmdBuffer;
1656 
1657         const auto vkSampleCount = (multiSample ? params.multiSampleCount : VK_SAMPLE_COUNT_1_BIT);
1658         const auto sampleCount   = static_cast<int32_t>(vkSampleCount);
1659 
1660         beginCommandBuffer(ctx.vkd, cmdBuffer);
1661         cmdPipelineMemoryBarrier(ctx.vkd, cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
1662                                  &hostToFragBarrier);
1663         ctx.vkd.cmdBeginRendering(cmdBuffer, &renderingInfo);
1664         ctx.vkd.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vbOffset);
1665         ctx.vkd.cmdBindDescriptorSets(cmdBuffer, bindPoint, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, nullptr);
1666         ctx.vkd.cmdBindPipeline(cmdBuffer, bindPoint, (multiSample ? *pipelineMulti : *pipelineSingle));
1667         ctx.vkd.cmdPushConstants(cmdBuffer, *pipelineLayout, dataStages, 0u, pcSize, &sampleCount);
1668         ctx.vkd.cmdDraw(cmdBuffer, de::sizeU32(vertices), 1u, 0u, 0u);
1669         ctx.vkd.cmdEndRendering(cmdBuffer);
1670         cmdPipelineMemoryBarrier(ctx.vkd, cmdBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
1671                                  &fragToHostBarrier);
1672         endCommandBuffer(ctx.vkd, cmdBuffer);
1673         submitCommandsAndWait(ctx.vkd, ctx.device, ctx.queue, cmdBuffer);
1674 
1675         // Verify buffer contents.
1676         invalidateAlloc(ctx.vkd, ctx.device, abAlloc);
1677         invalidateAlloc(ctx.vkd, ctx.device, pbAlloc);
1678 
1679         deMemcpy(&invocationCount, abData, sizeof(invocationCount));
1680         if (invocationCount <= 0 || invocationCount > sampleCount)
1681         {
1682             const auto prefix = (multiSample ? "[MultiSample]" : "[Single-Sample]");
1683             std::ostringstream msg;
1684             msg << prefix << " Invalid invocation count found in atomic buffer: expected value in range [1, "
1685                 << sampleCount << "] but found " << invocationCount;
1686             TCU_FAIL(msg.str());
1687         }
1688 
1689         const auto itr = locationsByCount.find(vkSampleCount);
1690         DE_ASSERT(itr != locationsByCount.end());
1691         const auto expectedLocations = itr->second;
1692 
1693         deMemcpy(de::dataOrNull(samplePositions), pbData, de::dataSize(samplePositions));
1694         for (int32_t invocationIdx = 0; invocationIdx < invocationCount; ++invocationIdx)
1695         {
1696             DE_ASSERT(expectedLocations->size() == static_cast<size_t>(vkSampleCount));
1697             const auto bufferOffset = invocationIdx * sampleCount;
1698             for (int32_t sampleIdx = 0; sampleIdx < sampleCount; ++sampleIdx)
1699             {
1700                 const auto &result   = samplePositions[bufferOffset + sampleIdx];
1701                 const auto &expected = expectedLocations->at(sampleIdx);
1702 
1703                 if (!tcu::boolAll(tcu::lessThanEqual(tcu::absDiff(result, expected),
1704                                                      tcu::Vec2(locationThreshold, locationThreshold))))
1705                 {
1706                     const auto prefix = (multiSample ? "[MultiSample]" : "[Single-Sample]");
1707                     std::ostringstream msg;
1708                     msg << prefix << " Unexpected position found for invocation " << invocationIdx << " sample "
1709                         << sampleIdx << ": expected " << expected << " but found " << result;
1710                     TCU_FAIL(msg.str());
1711                 }
1712             }
1713         }
1714     }
1715 
1716     return tcu::TestStatus::pass("Pass");
1717 }
1718 #endif // CTS_USES_VULKANSC
1719 
1720 } // namespace
1721 
createMiscTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType)1722 tcu::TestCaseGroup *createMiscTests(tcu::TestContext &testCtx, PipelineConstructionType pipelineConstructionType)
1723 {
1724     de::MovePtr<tcu::TestCaseGroup> miscTests(new tcu::TestCaseGroup(testCtx, "misc"));
1725 
1726     // Location of the Amber script files under the data/vulkan/amber source tree.
1727     if (pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
1728         addMonolithicAmberTests(miscTests.get());
1729 
1730     // Verify implicit access to gl_PrimtiveID works
1731     miscTests->addChild(
1732         new ImplicitPrimitiveIDPassthroughCase(testCtx, "implicit_primitive_id", pipelineConstructionType, false));
1733     // Verify implicit access to gl_PrimtiveID works with a tessellation shader
1734     miscTests->addChild(new ImplicitPrimitiveIDPassthroughCase(testCtx, "implicit_primitive_id_with_tessellation",
1735                                                                pipelineConstructionType, true));
1736 
1737     if (isConstructionTypeLibrary(pipelineConstructionType))
1738     {
1739         addFunctionCaseWithPrograms(miscTests.get(), "compatible_render_pass", checkCompatibleRenderPassSupport,
1740                                     initCompatibleRenderPassPrograms, compatibleRenderPassTest,
1741                                     pipelineConstructionType);
1742     }
1743 
1744 #ifndef CTS_USES_VULKANSC
1745     if (pipelineConstructionType == vk::PIPELINE_CONSTRUCTION_TYPE_FAST_LINKED_LIBRARY)
1746     {
1747         // Check if interpolateAtSample works as expected when using a pipeline library and null MSAA state in the fragment shader"
1748         miscTests->addChild(
1749             new PipelineLibraryInterpolateAtSampleTestCase(testCtx, "interpolate_at_sample_no_sample_shading"));
1750     }
1751 
1752     if (isConstructionTypeLibrary(pipelineConstructionType))
1753     {
1754         const VkSampleCountFlagBits sampleCounts[] = {
1755             VK_SAMPLE_COUNT_2_BIT,
1756             VK_SAMPLE_COUNT_4_BIT,
1757             VK_SAMPLE_COUNT_8_BIT,
1758             VK_SAMPLE_COUNT_16_BIT,
1759         };
1760         for (const auto sampleCount : sampleCounts)
1761         {
1762             const auto testName = "frag_lib_varying_samples_" + std::to_string(static_cast<int>(sampleCount));
1763             const VaryingSamplesFragParams params{pipelineConstructionType, sampleCount};
1764 
1765             addFunctionCaseWithPrograms(miscTests.get(), testName, checkVaryingSamplesFragSupport,
1766                                         initVaryingSamplesFragPrograms, varyingSamplesFragTest, params);
1767         }
1768     }
1769 #endif // CTS_USES_VULKANSC
1770 
1771     BindingTestConfig config0 = {pipelineConstructionType, true, false};
1772     BindingTestConfig config1 = {pipelineConstructionType, false, true};
1773     BindingTestConfig config2 = {pipelineConstructionType, true, true};
1774 
1775     // Verify implicit access to gl_PrimtiveID works with a tessellation shader
1776     miscTests->addChild(new PipelineLayoutBindingTestCases(testCtx, "descriptor_bind_test_backwards", config0));
1777     // Verify implicit access to gl_PrimtiveID works with a tessellation shader
1778     miscTests->addChild(new PipelineLayoutBindingTestCases(testCtx, "descriptor_bind_test_holes", config1));
1779     // Verify implicit access to gl_PrimtiveID works with a tessellation shader
1780     miscTests->addChild(new PipelineLayoutBindingTestCases(testCtx, "descriptor_bind_test_backwards_holes", config2));
1781 
1782     return miscTests.release();
1783 }
1784 
1785 } // namespace pipeline
1786 } // namespace vkt
1787