• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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         nullptr,                                                    // 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     static const VkPipelineColorBlendStateCreateInfo colorBlendState{
628         VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType                                sType
629         nullptr,                 // const void*                                    pNext
630         0u,                      // VkPipelineColorBlendStateCreateFlags            flags
631         VK_FALSE,                // VkBool32                                        logicOpEnable
632         VK_LOGIC_OP_CLEAR,       // VkLogicOp                                    logicOp
633         0u,                      // uint32_t                                        attachmentCount
634         nullptr,                 // const VkPipelineColorBlendAttachmentState*    pAttachments
635         {0.0f, 0.0f, 0.0f, 0.0f} // float                                        blendConstants[4]
636     };
637 
638     pipeline1.setDefaultTopology(vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
639         .setDefaultRasterizationState()
640         .setDefaultDepthStencilState()
641         .setupVertexInputState(&vertexInputState)
642         .setupPreRasterizationShaderState(viewports, scissors, graphicsPipelineLayout, VK_NULL_HANDLE, 0u, vtxshader)
643         .setupFragmentShaderState(graphicsPipelineLayout, VK_NULL_HANDLE, 0u, frgshader)
644         .setupFragmentOutputState(VK_NULL_HANDLE, 0u, &colorBlendState, &multisampling)
645         .setMonolithicPipelineLayout(graphicsPipelineLayout)
646         .buildPipeline();
647 
648     auto commandPool   = createCommandPool(vkd, device, vk::VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, qIndex);
649     auto commandBuffer = vk::allocateCommandBuffer(vkd, device, commandPool.get(), vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY);
650 
651     const auto clearValueColor = vk::makeClearValueColor(tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
652 
653     const vk::VkRect2D renderArea = {{0u, 0u}, {imageExtent.width, imageExtent.height}};
654 
655     const vk::VkRenderingAttachmentInfoKHR colorAttachments = {
656         vk::VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR, // VkStructureType sType;
657         nullptr,                                             // const void* pNext;
658         colorAttachmentView.get(),                           // VkImageView imageView;
659         vk::VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR,          // VkImageLayout imageLayout;
660         vk::VK_RESOLVE_MODE_NONE,                            // VkResolveModeFlagBits resolveMode;
661         VK_NULL_HANDLE,                                      // VkImageView resolveImageView;
662         vk::VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR,          // VkImageLayout resolveImageLayout;
663         vk::VK_ATTACHMENT_LOAD_OP_CLEAR,                     // VkAttachmentLoadOp loadOp;
664         vk::VK_ATTACHMENT_STORE_OP_STORE,                    // VkAttachmentStoreOp storeOp;
665         clearValueColor                                      // VkClearValue clearValue;
666     };
667     const VkRenderingInfoKHR render_info = {
668         VK_STRUCTURE_TYPE_RENDERING_INFO_KHR, 0, 0, renderArea, 1, 0, 1, &colorAttachments, nullptr, nullptr};
669 
670     vk::beginCommandBuffer(vkd, commandBuffer.get());
671     vk::VkImageMemoryBarrier initialBarrier =
672         makeImageMemoryBarrier(0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
673                                VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR, (*colorAttachment).get(), subresourceRange);
674     vkd.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
675                            VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0, nullptr, 0, nullptr, 1,
676                            &initialBarrier);
677     vkd.cmdBindDescriptorSets(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipelineLayout.get(), 0u, 1,
678                               &descriptorSetBuffer.get(), 0u, nullptr);
679 
680     vkd.cmdBeginRendering(*commandBuffer, &render_info);
681     pipeline1.bind(commandBuffer.get());
682     vkd.cmdDraw(commandBuffer.get(), 6, 1, 0, 0);
683     vkd.cmdEndRendering(*commandBuffer);
684 
685     const VkBufferMemoryBarrier indexBufferBarrier = makeBufferMemoryBarrier(
686         VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, index.get(), 0ull, sizeof(uint32_t));
687     vkd.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0,
688                            nullptr, 1, &indexBufferBarrier, 0, nullptr);
689 
690     const VkBufferMemoryBarrier valueBufferBarrier =
691         makeBufferMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, values.get(), 0ull, bufferSize);
692     vkd.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0,
693                            nullptr, 1, &valueBufferBarrier, 0, nullptr);
694 
695     vk::endCommandBuffer(vkd, commandBuffer.get());
696     vk::submitCommandsAndWait(vkd, device, m_context.getUniversalQueue(), commandBuffer.get());
697 }
698 
iterate(void)699 tcu::TestStatus PipelineLibraryInterpolateAtSampleTestInstance::iterate(void)
700 {
701     const auto &vkd   = m_context.getDeviceInterface();
702     const auto device = m_context.getDevice();
703     auto &alloc       = m_context.getDefaultAllocator();
704 
705     struct ValueBuffer
706     {
707         float values[PipelineLibraryInterpolateAtSampleTestCase::ResultCount];
708     };
709 
710     size_t resultSize = PipelineLibraryInterpolateAtSampleTestCase::ResultCount;
711 
712     const auto indexBufferSize = static_cast<VkDeviceSize>(sizeof(uint32_t));
713     const auto valueBufferSize = static_cast<VkDeviceSize>(sizeof(ValueBuffer));
714 
715     auto indexCreateInfo  = makeBufferCreateInfo(indexBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
716     auto valuesCreateInfo = makeBufferCreateInfo(valueBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
717 
718     BufferWithMemory indexBufferMonolithic(vkd, device, alloc, indexCreateInfo, MemoryRequirement::HostVisible);
719     BufferWithMemory valuesBufferMonolithic(vkd, device, alloc, valuesCreateInfo, MemoryRequirement::HostVisible);
720     BufferWithMemory indexBufferGPL(vkd, device, alloc, indexCreateInfo, MemoryRequirement::HostVisible);
721     BufferWithMemory valuesBufferGPL(vkd, device, alloc, valuesCreateInfo, MemoryRequirement::HostVisible);
722 
723     auto &indexBufferMonolithicAlloc  = indexBufferMonolithic.getAllocation();
724     auto &valuesBufferMonolithicAlloc = valuesBufferMonolithic.getAllocation();
725     auto &indexBufferGPLAlloc         = indexBufferGPL.getAllocation();
726     auto &valuesBufferGPLAlloc        = valuesBufferGPL.getAllocation();
727 
728     void *indexBufferMonolithicData  = indexBufferMonolithicAlloc.getHostPtr();
729     void *valuesBufferMonolithicData = valuesBufferMonolithicAlloc.getHostPtr();
730     void *indexBufferGPLData         = indexBufferGPLAlloc.getHostPtr();
731     void *valuesBufferGPLData        = valuesBufferGPLAlloc.getHostPtr();
732 
733     deMemset(indexBufferMonolithicData, 0, sizeof(uint32_t));
734     deMemset(valuesBufferMonolithicData, 0, sizeof(ValueBuffer));
735     deMemset(indexBufferGPLData, 0, sizeof(uint32_t));
736     deMemset(valuesBufferGPLData, 0, sizeof(ValueBuffer));
737 
738     flushAlloc(vkd, device, indexBufferMonolithicAlloc);
739     flushAlloc(vkd, device, valuesBufferMonolithicAlloc);
740     flushAlloc(vkd, device, indexBufferGPLAlloc);
741     flushAlloc(vkd, device, valuesBufferGPLAlloc);
742 
743     runTest(indexBufferMonolithic, valuesBufferMonolithic, valueBufferSize, vk::PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC);
744     runTest(indexBufferGPL, valuesBufferGPL, valueBufferSize, vk::PIPELINE_CONSTRUCTION_TYPE_FAST_LINKED_LIBRARY);
745 
746     invalidateAlloc(vkd, device, indexBufferMonolithicAlloc);
747     invalidateAlloc(vkd, device, valuesBufferMonolithicAlloc);
748     invalidateAlloc(vkd, device, indexBufferGPLAlloc);
749     invalidateAlloc(vkd, device, valuesBufferGPLAlloc);
750 
751     uint32_t monolithicIndex;
752     uint32_t GPLIndex;
753     struct ValueBuffer monolithicResult = ValueBuffer();
754     struct ValueBuffer GPLResult        = ValueBuffer();
755     memcpy((void *)&monolithicIndex, indexBufferMonolithicData, sizeof(uint32_t));
756     memcpy((void *)&GPLIndex, indexBufferGPLData, sizeof(uint32_t));
757     memcpy((void *)&monolithicResult, valuesBufferMonolithicData, sizeof(ValueBuffer));
758     memcpy((void *)&GPLResult, valuesBufferGPLData, sizeof(ValueBuffer));
759 
760     //we can't know which order the shaders will run in
761     std::sort(monolithicResult.values, monolithicResult.values + resultSize);
762     std::sort(GPLResult.values, GPLResult.values + resultSize);
763 
764     //check that the atomic counters are at enough for the number of invocations
765     constexpr int expected = (PipelineLibraryInterpolateAtSampleTestCase::sampleCount + 1) *
766                              PipelineLibraryInterpolateAtSampleTestCase::width *
767                              PipelineLibraryInterpolateAtSampleTestCase::height;
768 
769     if (monolithicIndex < expected && GPLIndex < expected)
770     {
771         return tcu::TestStatus::fail("Atomic counter value lower than expected");
772     }
773 
774     for (uint32_t i = 1; i < PipelineLibraryInterpolateAtSampleTestCase::ResultCount; i++)
775     {
776         if (monolithicResult.values[i] != monolithicResult.values[i])
777         {
778             return tcu::TestStatus::fail("Comparison failed");
779         }
780     }
781 
782     return tcu::TestStatus::pass("Pass");
783 }
784 #endif
785 
786 struct BindingTestConfig
787 {
788     PipelineConstructionType construction;
789     bool backwardsBinding;
790     bool holes;
791 };
792 
793 /*
794  * Test the following behaviours:
795  * Descriptor sets updated/bound in backwards order
796  * Descriptor sets with index holes updated/bound/used
797  */
798 class PipelineLayoutBindingTestCases : public vkt::TestCase
799 {
800 public:
PipelineLayoutBindingTestCases(tcu::TestContext & testCtx,const std::string & name,const BindingTestConfig & config)801     PipelineLayoutBindingTestCases(tcu::TestContext &testCtx, const std::string &name, const BindingTestConfig &config)
802         : vkt::TestCase(testCtx, name)
803         , m_config(config)
804     {
805     }
~PipelineLayoutBindingTestCases(void)806     ~PipelineLayoutBindingTestCases(void)
807     {
808     }
809     void initPrograms(SourceCollections &programCollection) const override;
810     void checkSupport(Context &context) const override;
811     TestInstance *createInstance(Context &context) const override;
812 
813     const BindingTestConfig m_config;
814 };
815 
816 class PipelineLayoutBindingTestInstance : public vkt::TestInstance
817 {
818 public:
PipelineLayoutBindingTestInstance(Context & context,const BindingTestConfig & config)819     PipelineLayoutBindingTestInstance(Context &context, const BindingTestConfig &config)
820         : vkt::TestInstance(context)
821         , m_renderSize(2, 2)
822         , m_extent(makeExtent3D(m_renderSize.x(), m_renderSize.y(), 1u))
823         , m_format(VK_FORMAT_R8G8B8A8_UNORM)
824         , m_graphicsPipeline(context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(),
825                              context.getDevice(), context.getDeviceExtensions(), config.construction)
826         , m_config(config)
827     {
828     }
~PipelineLayoutBindingTestInstance(void)829     ~PipelineLayoutBindingTestInstance(void)
830     {
831     }
832     tcu::TestStatus iterate(void) override;
833 
834 private:
835     const tcu::UVec2 m_renderSize;
836     const VkExtent3D m_extent;
837     const VkFormat m_format;
838     GraphicsPipelineWrapper m_graphicsPipeline;
839     const BindingTestConfig m_config;
840 };
841 
createInstance(Context & context) const842 TestInstance *PipelineLayoutBindingTestCases::createInstance(Context &context) const
843 {
844     return new PipelineLayoutBindingTestInstance(context, m_config);
845 }
846 
checkSupport(Context & context) const847 void PipelineLayoutBindingTestCases::checkSupport(Context &context) const
848 {
849     checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(),
850                                           m_config.construction);
851 }
852 
initPrograms(SourceCollections & sources) const853 void PipelineLayoutBindingTestCases::initPrograms(SourceCollections &sources) const
854 {
855     std::ostringstream src;
856     src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
857         << "vec2 positions[3] = vec2[](\n"
858         << "        vec2(-1.0, -1.0),"
859         << "        vec2(3.0, -1.0),"
860         << "        vec2(-1.0, 3.0)"
861         << ");\n"
862         << "void main() {\n"
863         << "        gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);\n"
864         << "}";
865     sources.glslSources.add("vert") << glu::VertexSource(src.str());
866 
867     std::ostringstream frag;
868     frag << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
869          << "layout (location=0) out vec4 outColor;\n"
870          << "layout(set = 0, binding = 0) uniform Output0 {"
871          << "    uint data;"
872          << "} buf0;\n";
873     if (!m_config.holes)
874     {
875         frag << "layout(set = 1, binding = 0) uniform Output1 {"
876              << "    uint data;"
877              << "} buf1;\n"
878              << "layout(set = 2, binding = 0) uniform Output2 {"
879              << "    uint data;"
880              << "} buf2;\n"
881              << "\n";
882     }
883     frag << "layout(set = 3, binding = 0) uniform Output3 {"
884          << "    uint data;"
885          << "} buf3;\n"
886          << "void main ()\n"
887          << "{\n"
888          << "    const vec4 red = vec4(1.0, 0.0, 0.0, 1.0);\n"
889          << "    const vec4 green = vec4(0.0, 1.0, 0.0, 1.0);\n";
890     if (!m_config.holes)
891     {
892         frag << "    outColor = ((buf0.data == 0) && (buf1.data == 1) && (buf2.data == 2) && (buf3.data == 3)) ? green "
893                 ": red;\n";
894     }
895     else
896     {
897         frag << "    outColor = ((buf0.data == 0) && (buf3.data == 3)) ? green : red;\n";
898     }
899     frag << "}\n";
900     sources.glslSources.add("frag") << glu::FragmentSource(frag.str());
901 }
902 
iterate()903 tcu::TestStatus PipelineLayoutBindingTestInstance::iterate()
904 {
905     const auto &vkd             = m_context.getDeviceInterface();
906     const auto device           = m_context.getDevice();
907     auto &alloc                 = m_context.getDefaultAllocator();
908     const auto qIndex           = m_context.getUniversalQueueFamilyIndex();
909     const auto queue            = m_context.getUniversalQueue();
910     const auto tcuFormat        = mapVkFormat(m_format);
911     const auto colorUsage       = (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
912     const auto verifBufferUsage = VK_BUFFER_USAGE_TRANSFER_DST_BIT;
913     const tcu::Vec4 clearColor(0.0f, 0.0f, 0.0f, 1.0f);
914 
915     // Color attachment.
916     const VkImageCreateInfo colorBufferInfo = {
917         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
918         nullptr,                             // const void* pNext;
919         0u,                                  // VkImageCreateFlags flags;
920         VK_IMAGE_TYPE_2D,                    // VkImageType imageType;
921         m_format,                            // VkFormat format;
922         m_extent,                            // VkExtent3D extent;
923         1u,                                  // uint32_t mipLevels;
924         1u,                                  // uint32_t arrayLayers;
925         VK_SAMPLE_COUNT_1_BIT,               // VkSampleCountFlagBits samples;
926         VK_IMAGE_TILING_OPTIMAL,             // VkImageTiling tiling;
927         colorUsage,                          // VkImageUsageFlags usage;
928         VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode sharingMode;
929         0u,                                  // uint32_t queueFamilyIndexCount;
930         nullptr,                             // const uint32_t* pQueueFamilyIndices;
931         VK_IMAGE_LAYOUT_UNDEFINED,           // VkImageLayout initialLayout;
932     };
933     ImageWithMemory colorBuffer(vkd, device, alloc, colorBufferInfo, MemoryRequirement::Any);
934     const auto colorSRR = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
935     const auto colorSRL = makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
936     const auto colorBufferView =
937         makeImageView(vkd, device, colorBuffer.get(), VK_IMAGE_VIEW_TYPE_2D, m_format, colorSRR);
938 
939     // Verification buffer.
940     const auto verifBufferSize =
941         static_cast<VkDeviceSize>(tcu::getPixelSize(tcuFormat)) * m_extent.width * m_extent.height;
942     const auto verifBufferInfo = makeBufferCreateInfo(verifBufferSize, verifBufferUsage);
943     BufferWithMemory verifBuffer(vkd, device, alloc, verifBufferInfo, MemoryRequirement::HostVisible);
944     auto &verifBufferAlloc = verifBuffer.getAllocation();
945 
946     // Render pass and framebuffer.
947     RenderPassWrapper renderPass(m_config.construction, vkd, device, m_format);
948     renderPass.createFramebuffer(vkd, device, colorBuffer.get(), colorBufferView.get(), m_extent.width,
949                                  m_extent.height);
950 
951     // Shader modules.
952     const auto &binaries  = m_context.getBinaryCollection();
953     const auto vertModule = ShaderWrapper(vkd, device, binaries.get("vert"));
954     const auto fragModule = ShaderWrapper(vkd, device, binaries.get("frag"));
955 
956     // Viewports and scissors.
957     const std::vector<VkViewport> viewports(1u, makeViewport(m_extent));
958     const std::vector<VkRect2D> scissors(1u, makeRect2D(m_extent));
959 
960     const VkPipelineVertexInputStateCreateInfo vertexInputState     = initVulkanStructure();
961     const VkPipelineRasterizationStateCreateInfo rasterizationState = {
962         VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType                          sType;
963         nullptr,                                                    // const void*                              pNext;
964         (VkPipelineRasterizationStateCreateFlags)0,                 // VkPipelineRasterizationStateCreateFlags  flags;
965         VK_FALSE,                // VkBool32                                 depthClampEnable;
966         VK_FALSE,                // VkBool32                                 rasterizerDiscardEnable;
967         VK_POLYGON_MODE_FILL,    // VkPolygonMode polygonMode;
968         VK_CULL_MODE_NONE,       // VkCullModeFlags cullMode;
969         VK_FRONT_FACE_CLOCKWISE, // VkFrontFace frontFace;
970         VK_FALSE,                // VkBool32 depthBiasEnable;
971         0.0f,                    // float depthBiasConstantFactor;
972         0.0f,                    // float depthBiasClamp;
973         0.0f,                    // float depthBiasSlopeFactor;
974         1.0f,                    // float lineWidth;
975     };
976 
977     std::array<int, 4> tmpIndices = {};
978     std::array<int, 4> indices    = {};
979     std::iota(tmpIndices.begin(), tmpIndices.end(), 0);
980     if (m_config.backwardsBinding)
981     {
982         std::copy(tmpIndices.rbegin(), tmpIndices.rend(), indices.begin());
983     }
984     else
985     {
986         std::copy(tmpIndices.begin(), tmpIndices.end(), indices.begin());
987     }
988 
989     vk::DescriptorSetLayoutBuilder layoutBuilder;
990     layoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT);
991 
992     std::vector<vk::Move<VkDescriptorSetLayout>> descriptorSetLayouts = {};
993 
994     for (size_t i = 0; i < indices.size(); i++)
995     {
996         descriptorSetLayouts.emplace_back(layoutBuilder.build(vkd, device));
997     }
998 
999     // Pipeline layout and graphics pipeline.
1000     uint32_t setAndDescriptorCount = de::sizeU32(indices);
1001     const vk::PipelineLayoutWrapper pipelineLayout(m_config.construction, vkd, device, descriptorSetLayouts);
1002     DescriptorPoolBuilder poolBuilder;
1003     poolBuilder.addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, setAndDescriptorCount);
1004     const auto descriptorPool =
1005         poolBuilder.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, setAndDescriptorCount);
1006     std::vector<vk::Move<VkDescriptorSet>> descriptorSetsWrap = {};
1007     std::vector<VkDescriptorSet> descriptorSets               = {};
1008 
1009     for (const auto &setLayout : descriptorSetLayouts)
1010     {
1011         descriptorSetsWrap.emplace_back(makeDescriptorSet(vkd, device, descriptorPool.get(), setLayout.get()));
1012     }
1013 
1014     for (size_t i = 0; i < indices.size(); i++)
1015     {
1016         descriptorSets.emplace_back(descriptorSetsWrap[i].get());
1017     }
1018 
1019     const auto bufferSize = static_cast<VkDeviceSize>(sizeof(uint32_t));
1020     std::vector<std::unique_ptr<BufferWithMemory>> buffers;
1021     //create uniform buffers
1022     for (size_t i = 0; i < indices.size(); i++)
1023     {
1024         auto outBufferInfo = makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
1025         auto buffer        = std::unique_ptr<vk::BufferWithMemory>(
1026             new vk::BufferWithMemory(vkd, device, alloc, outBufferInfo, vk::MemoryRequirement::HostVisible));
1027         auto &bufferAlloc    = buffer->getAllocation();
1028         uint32_t *bufferData = (uint32_t *)bufferAlloc.getHostPtr();
1029         *bufferData          = (uint32_t)i;
1030         flushAlloc(vkd, device, bufferAlloc);
1031         buffers.push_back(std::move(buffer));
1032     }
1033 
1034     DescriptorSetUpdateBuilder updater;
1035 
1036     for (auto i : indices)
1037     {
1038         const auto bufferInfo = makeDescriptorBufferInfo(buffers[i]->get(), 0ull, bufferSize);
1039         updater.writeSingle(descriptorSets[i], DescriptorSetUpdateBuilder::Location::binding(0),
1040                             VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &bufferInfo);
1041         updater.update(vkd, device);
1042     }
1043 
1044     const auto topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
1045     m_graphicsPipeline.setDefaultRasterizationState()
1046         .setDefaultTopology(topology)
1047         .setupVertexInputState(&vertexInputState)
1048         .setDefaultDepthStencilState()
1049         .setDefaultMultisampleState()
1050         .setDefaultColorBlendState()
1051         .setupPreRasterizationShaderState(viewports, scissors, pipelineLayout, *renderPass, 0u, vertModule,
1052                                           &rasterizationState)
1053         .setupFragmentShaderState(pipelineLayout, *renderPass, 0u, fragModule)
1054         .setupFragmentOutputState(*renderPass)
1055         .setMonolithicPipelineLayout(pipelineLayout)
1056         .buildPipeline();
1057 
1058     // Command pool and buffer.
1059     const auto cmdPool      = makeCommandPool(vkd, device, qIndex);
1060     const auto cmdBufferPtr = allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1061     const auto cmdBuffer    = cmdBufferPtr.get();
1062 
1063     beginCommandBuffer(vkd, cmdBuffer);
1064 
1065     // Draw.
1066     renderPass.begin(vkd, cmdBuffer, scissors.at(0u), clearColor);
1067     for (auto i : indices)
1068     {
1069         if (m_config.holes && ((i == 1) || (i == 2)))
1070         {
1071             continue;
1072         }
1073         vkd.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), i, 1,
1074                                   &descriptorSets[i], 0u, nullptr);
1075     }
1076     m_graphicsPipeline.bind(cmdBuffer);
1077     vkd.cmdDraw(cmdBuffer, 3, 1u, 0u, 0u);
1078     renderPass.end(vkd, cmdBuffer);
1079 
1080     // Copy to verification buffer.
1081     const auto copyRegion     = makeBufferImageCopy(m_extent, colorSRL);
1082     const auto transfer2Host  = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
1083     const auto color2Transfer = makeImageMemoryBarrier(
1084         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
1085         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, colorBuffer.get(), colorSRR);
1086 
1087     cmdPipelineImageMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
1088                                   VK_PIPELINE_STAGE_TRANSFER_BIT, &color2Transfer);
1089     vkd.cmdCopyImageToBuffer(cmdBuffer, colorBuffer.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, verifBuffer.get(), 1u,
1090                              &copyRegion);
1091     cmdPipelineMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
1092                              &transfer2Host);
1093 
1094     endCommandBuffer(vkd, cmdBuffer);
1095 
1096     // Submit and validate result.
1097     submitCommandsAndWait(vkd, device, queue, cmdBuffer);
1098 
1099     const tcu::IVec3 iExtent(static_cast<int>(m_extent.width), static_cast<int>(m_extent.height),
1100                              static_cast<int>(m_extent.depth));
1101     void *verifBufferData = verifBufferAlloc.getHostPtr();
1102     const tcu::ConstPixelBufferAccess verifAccess(tcuFormat, iExtent, verifBufferData);
1103     invalidateAlloc(vkd, device, verifBufferAlloc);
1104 
1105     const auto green = tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f);
1106     tcu::TextureLevel referenceLevel(mapVkFormat(m_format), m_extent.height, m_extent.height);
1107     tcu::PixelBufferAccess reference = referenceLevel.getAccess();
1108     tcu::clear(reference, green);
1109 
1110     if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", reference,
1111                                     verifAccess, tcu::Vec4(0.0), tcu::COMPARE_LOG_ON_ERROR))
1112         return tcu::TestStatus::fail("Image comparison failed");
1113 
1114     return tcu::TestStatus::pass("Pass");
1115 }
1116 
initCompatibleRenderPassPrograms(SourceCollections & dst,PipelineConstructionType)1117 void initCompatibleRenderPassPrograms(SourceCollections &dst, PipelineConstructionType)
1118 {
1119     std::ostringstream vert;
1120     vert << "#version 460\n"
1121          << "vec2 positions[] = vec2[](\n"
1122          << "    vec2(-1.0, -1.0),\n"
1123          << "    vec2( 3.0, -1.0),\n"
1124          << "    vec2(-1.0,  3.0)\n"
1125          << ");\n"
1126          << "void main (void) {\n"
1127          << "    gl_Position = vec4(positions[gl_VertexIndex % 3], 0.0, 1.0);\n"
1128          << "}\n";
1129     dst.glslSources.add("vert") << glu::VertexSource(vert.str());
1130 
1131     std::ostringstream frag;
1132     frag << "#version 460\n"
1133          << "layout (location=0) out vec4 outColor;\n"
1134          << "void main (void) {\n"
1135          << "    outColor = vec4(0.0, 0.0, 1.0, 1.0);\n"
1136          << "}\n";
1137     dst.glslSources.add("frag") << glu::FragmentSource(frag.str());
1138 }
1139 
checkCompatibleRenderPassSupport(Context & context,PipelineConstructionType pipelineConstructionType)1140 void checkCompatibleRenderPassSupport(Context &context, PipelineConstructionType pipelineConstructionType)
1141 {
1142     const auto &vki           = context.getInstanceInterface();
1143     const auto physicalDevice = context.getPhysicalDevice();
1144 
1145     checkPipelineConstructionRequirements(vki, physicalDevice, pipelineConstructionType);
1146 }
1147 
compatibleRenderPassTest(Context & context,PipelineConstructionType pipelineConstructionType)1148 tcu::TestStatus compatibleRenderPassTest(Context &context, PipelineConstructionType pipelineConstructionType)
1149 {
1150     const auto &ctx = context.getContextCommonData();
1151     const tcu::IVec3 fbExtent(1, 1, 1);
1152     const auto vkExtent  = makeExtent3D(fbExtent);
1153     const auto fbFormat  = VK_FORMAT_R8G8B8A8_UNORM;
1154     const auto tcuFormat = mapVkFormat(fbFormat);
1155     const auto fbUsage   = (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
1156     const tcu::Vec4 clearColor(0.0f, 0.0f, 0.0f, 1.0f);
1157     const tcu::Vec4 geomColor(0.0f, 0.0f, 1.0f, 1.0f); // Must match frag shader.
1158     const tcu::Vec4 threshold(0.0f, 0.0f, 0.0f, 0.0f); // When using 0 and 1 only, we expect exact results.
1159 
1160     // Color buffer with verification buffer.
1161     ImageWithBuffer colorBuffer(ctx.vkd, ctx.device, ctx.allocator, vkExtent, fbFormat, fbUsage, VK_IMAGE_TYPE_2D);
1162 
1163     const PipelineLayoutWrapper pipelineLayout(pipelineConstructionType, ctx.vkd, ctx.device);
1164     auto renderPass         = makeRenderPass(ctx.vkd, ctx.device, fbFormat);
1165     const auto compatibleRP = makeRenderPass(ctx.vkd, ctx.device, fbFormat);
1166     const auto framebuffer =
1167         makeFramebuffer(ctx.vkd, ctx.device, *renderPass, colorBuffer.getImageView(), vkExtent.width, vkExtent.height);
1168 
1169     // Modules.
1170     const auto &binaries = context.getBinaryCollection();
1171     const ShaderWrapper vertModule(ctx.vkd, ctx.device, binaries.get("vert"));
1172     const ShaderWrapper fragModule(ctx.vkd, ctx.device, binaries.get("frag"));
1173 
1174     const std::vector<VkViewport> viewports(1u, makeViewport(vkExtent));
1175     const std::vector<VkRect2D> scissors(1u, makeRect2D(vkExtent));
1176 
1177     // Empty vertex input state.
1178     const VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo = initVulkanStructure();
1179 
1180     GraphicsPipelineWrapper pipelineWrapper(ctx.vki, ctx.vkd, ctx.physicalDevice, ctx.device,
1181                                             context.getDeviceExtensions(), pipelineConstructionType);
1182 
1183     pipelineWrapper.setDefaultTopology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
1184         .setDefaultRasterizationState()
1185         .setDefaultColorBlendState()
1186         .setDefaultMultisampleState()
1187         .setDefaultDepthStencilState()
1188         .setupVertexInputState(&vertexInputStateCreateInfo)
1189         .setupPreRasterizationShaderState(viewports, scissors, pipelineLayout, *renderPass, 0u, vertModule)
1190         .setupFragmentShaderState(pipelineLayout, *renderPass, 0u, fragModule)
1191         .setupFragmentOutputState(*renderPass);
1192 
1193     // Important: at this point, the 4 libraries should have been created. Now we destroy the original render pass to make sure it's
1194     // no longer used, and use the compatible one for the remainder of the test.
1195     renderPass = Move<VkRenderPass>();
1196 
1197     // Finally, we link the complete pipeline and use the compatible render pass in the command buffer.
1198     DE_ASSERT(isConstructionTypeLibrary(pipelineConstructionType));
1199     pipelineWrapper.setMonolithicPipelineLayout(pipelineLayout).buildPipeline();
1200 
1201     CommandPoolWithBuffer cmd(ctx.vkd, ctx.device, ctx.qfIndex);
1202     const auto cmdBuffer = *cmd.cmdBuffer;
1203 
1204     beginCommandBuffer(ctx.vkd, cmdBuffer);
1205     beginRenderPass(ctx.vkd, cmdBuffer, *compatibleRP, *framebuffer, scissors.at(0u), clearColor);
1206     pipelineWrapper.bind(cmdBuffer);
1207     ctx.vkd.cmdDraw(cmdBuffer, 3u, 1u, 0u, 0u);
1208     endRenderPass(ctx.vkd, cmdBuffer);
1209     copyImageToBuffer(ctx.vkd, cmdBuffer, colorBuffer.getImage(), colorBuffer.getBuffer(), fbExtent.swizzle(0, 1),
1210                       VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 1u,
1211                       VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_ASPECT_COLOR_BIT,
1212                       VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
1213     endCommandBuffer(ctx.vkd, cmdBuffer);
1214     submitCommandsAndWait(ctx.vkd, ctx.device, ctx.queue, cmdBuffer);
1215 
1216     // Verify color output.
1217     invalidateAlloc(ctx.vkd, ctx.device, colorBuffer.getBufferAllocation());
1218     tcu::PixelBufferAccess resultAccess(tcuFormat, fbExtent, colorBuffer.getBufferAllocation().getHostPtr());
1219 
1220     tcu::TextureLevel referenceLevel(tcuFormat, fbExtent.x(), fbExtent.y());
1221     auto referenceAccess = referenceLevel.getAccess();
1222     tcu::clear(referenceAccess, geomColor);
1223 
1224     auto &log = context.getTestContext().getLog();
1225     if (!tcu::floatThresholdCompare(log, "Result", "", referenceAccess, resultAccess, threshold,
1226                                     tcu::COMPARE_LOG_ON_ERROR))
1227         return tcu::TestStatus::fail("Unexpected color in result buffer; check log for details");
1228 
1229     return tcu::TestStatus::pass("Pass");
1230 }
1231 
initArrayOfStructsInterfacePrograms(SourceCollections & dst,PipelineConstructionType)1232 void initArrayOfStructsInterfacePrograms(SourceCollections &dst, PipelineConstructionType)
1233 {
1234     // the purpose of tests is to check that sending struct between shaders stages does not crash the driver
1235     dst.glslSources.add("vert") << glu::VertexSource("#version 450\n"
1236                                                      "struct R { vec4 rgba; };\n"
1237                                                      "layout(location = 0) out R outColor[3];\n"
1238                                                      "void main (void)\n"
1239                                                      "{\n"
1240                                                      "  outColor[0].rgba = vec4(0.0, 0.9, 0.0, 1.0);\n"
1241                                                      "  outColor[1].rgba = vec4(0.3, 0.0, 0.0, 1.0);\n"
1242                                                      "  outColor[2].rgba = vec4(0.0, 0.0, 0.6, 1.0);\n"
1243                                                      "  const float x = (-1.0+2.0*((gl_VertexIndex & 2)>>1));\n"
1244                                                      "  const float y = ( 1.0-2.0* (gl_VertexIndex % 2));\n"
1245                                                      "  gl_Position = vec4(x, y, 0.6, 1.0);\n"
1246                                                      "}\n");
1247 
1248     dst.glslSources.add("frag") << glu::FragmentSource(
1249         "#version 450\n"
1250         "struct R { vec4 rgba; };\n"
1251         "layout(location = 0) in R inColor[3];\n"
1252         "layout(location = 0) out vec4 color;\n"
1253         "void main() {\n"
1254         "    color = inColor[2].rgba + inColor[1].rgba + inColor[0].rgba;\n"
1255         "}\n");
1256 }
1257 
checkArrayOfStructsInterfaceSupport(Context & context,PipelineConstructionType pipelineConstructionType)1258 void checkArrayOfStructsInterfaceSupport(Context &context, PipelineConstructionType pipelineConstructionType)
1259 {
1260     const auto &vki           = context.getInstanceInterface();
1261     const auto physicalDevice = context.getPhysicalDevice();
1262 
1263     checkPipelineConstructionRequirements(vki, physicalDevice, pipelineConstructionType);
1264 }
1265 
arrayOfStructsInterfaceTest(Context & context,PipelineConstructionType pipelineConstructionType)1266 tcu::TestStatus arrayOfStructsInterfaceTest(Context &context, PipelineConstructionType pipelineConstructionType)
1267 {
1268     const DeviceInterface &vk             = context.getDeviceInterface();
1269     const InstanceInterface &vki          = context.getInstanceInterface();
1270     const VkDevice device                 = context.getDevice();
1271     const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
1272     Allocator &memAlloc                   = context.getDefaultAllocator();
1273     const uint32_t queueFamilyIndex       = context.getUniversalQueueFamilyIndex();
1274     const tcu::IVec3 fbExtent(4, 4, 1);
1275     const auto vkExtent  = makeExtent3D(fbExtent);
1276     const auto fbFormat  = VK_FORMAT_R8G8B8A8_UNORM;
1277     const auto tcuFormat = mapVkFormat(fbFormat);
1278     const auto fbUsage   = (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
1279     const tcu::Vec4 clearColor(0.00f, 0.00f, 0.00f, 1.0f);
1280     const tcu::Vec4 expecColor(0.30f, 0.90f, 0.60f, 1.0f);
1281     const tcu::Vec4 threshold(0.02f, 0.02f, 0.02f, 0.0f);
1282 
1283     // Color buffer with verification buffer
1284     ImageWithBuffer colorBuffer(vk, device, memAlloc, vkExtent, fbFormat, fbUsage, VK_IMAGE_TYPE_2D);
1285     RenderPassWrapper renderPass(pipelineConstructionType, vk, device, fbFormat);
1286     renderPass.createFramebuffer(vk, device, colorBuffer.getImage(), colorBuffer.getImageView(), fbExtent.x(),
1287                                  fbExtent.y());
1288 
1289     const auto &binaries(context.getBinaryCollection());
1290     const ShaderWrapper vertModule(vk, device, binaries.get("vert"));
1291     const ShaderWrapper fragModule(vk, device, binaries.get("frag"));
1292     const PipelineLayoutWrapper pipelineLayout(pipelineConstructionType, vk, device);
1293 
1294     const std::vector<VkViewport> viewports{makeViewport(vkExtent)};
1295     const std::vector<VkRect2D> scissors{makeRect2D(vkExtent)};
1296 
1297     VkPipelineVertexInputStateCreateInfo vertexInputState = initVulkanStructure();
1298     GraphicsPipelineWrapper pipelineWrapper(vki, vk, physicalDevice, device, context.getDeviceExtensions(),
1299                                             pipelineConstructionType);
1300     pipelineWrapper.setDefaultTopology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP)
1301         .setDefaultRasterizationState()
1302         .setDefaultColorBlendState()
1303         .setDefaultMultisampleState()
1304         .setDefaultDepthStencilState()
1305         .setupVertexInputState(&vertexInputState)
1306         .setupPreRasterizationShaderState(viewports, scissors, pipelineLayout, *renderPass, 0u, vertModule)
1307         .setupFragmentShaderState(pipelineLayout, *renderPass, 0u, fragModule)
1308         .setupFragmentOutputState(*renderPass)
1309         .setMonolithicPipelineLayout(pipelineLayout)
1310         .buildPipeline();
1311 
1312     CommandPoolWithBuffer cmd(vk, device, queueFamilyIndex);
1313     const auto cmdBuffer = *cmd.cmdBuffer;
1314 
1315     beginCommandBuffer(vk, cmdBuffer);
1316 
1317     renderPass.begin(vk, cmdBuffer, scissors.at(0u), clearColor);
1318     pipelineWrapper.bind(cmdBuffer);
1319     vk.cmdDraw(cmdBuffer, 4u, 1u, 0u, 0u);
1320     renderPass.end(vk, cmdBuffer);
1321 
1322     copyImageToBuffer(vk, cmdBuffer, colorBuffer.getImage(), colorBuffer.getBuffer(), fbExtent.swizzle(0, 1),
1323                       VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 1u,
1324                       VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_ASPECT_COLOR_BIT,
1325                       VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
1326 
1327     endCommandBuffer(vk, cmdBuffer);
1328     submitCommandsAndWait(vk, device, context.getUniversalQueue(), cmdBuffer);
1329 
1330     invalidateAlloc(vk, device, colorBuffer.getBufferAllocation());
1331     tcu::PixelBufferAccess resultAccess(tcuFormat, fbExtent, colorBuffer.getBufferAllocation().getHostPtr());
1332     tcu::TextureLevel referenceLevel(tcuFormat, fbExtent.x(), fbExtent.y());
1333     auto referenceAccess = referenceLevel.getAccess();
1334     tcu::clear(referenceAccess, expecColor);
1335 
1336     auto &log = context.getTestContext().getLog();
1337     if (!tcu::floatThresholdCompare(log, "Result", "", referenceAccess, resultAccess, threshold,
1338                                     tcu::COMPARE_LOG_ON_ERROR))
1339         return tcu::TestStatus::fail("Unexpected color in result buffer; check log for details");
1340 
1341     return tcu::TestStatus::pass("Pass");
1342 }
1343 
1344 #ifndef CTS_USES_VULKANSC
1345 struct VaryingSamplesFragParams
1346 {
1347     const PipelineConstructionType constructionType;
1348     const VkSampleCountFlagBits multiSampleCount;
1349 };
1350 
initVaryingSamplesFragPrograms(SourceCollections & dst,VaryingSamplesFragParams)1351 void initVaryingSamplesFragPrograms(SourceCollections &dst, VaryingSamplesFragParams)
1352 {
1353     // The framebuffer will contain a single pixel and we will draw a quad using the 4 pixel corners. inSamplePos will contain 0s
1354     // and 1s in the X and Y values so that the value at each corner will match its corresponding sample location. The result is
1355     // that interpolating outSamplePos for a sample will give you the corresponding standard sample location.
1356     std::ostringstream vert;
1357     vert << "#version 460\n"
1358          << "layout (location=0) in vec4 inPos;\n"
1359          << "layout (location=1) in vec4 inSamplePos;\n"
1360          << "layout (location=0) out vec2 outSamplePos;\n"
1361          << "void main (void) {\n"
1362          << "    gl_Position = inPos;\n"
1363          << "    outSamplePos = inSamplePos.xy;\n"
1364          << "}\n";
1365     dst.glslSources.add("vert") << glu::VertexSource(vert.str());
1366 
1367     // Each frag shader invocation will interpolate the sample position for every sample, and will store the results of every
1368     // interpolation in the positions buffer. So if we work with 4 samples but get 2 actual invocations (e.g.):
1369     // - sampleCount from the push constants will be 4.
1370     // - mySampleId will end up containing 2.
1371     // - samplePositions will have 2 blocks of 4 results each, with the 4 interpolations for the first and second invocations.
1372     std::ostringstream frag;
1373     frag << "#version 460\n"
1374          << "layout (location=0) in vec2 inSamplePos;\n"
1375          << "layout (push_constant, std430) uniform PushConstantBlock { int sampleCount; } pc;\n"
1376          << "layout (set=0, binding=0, std430) buffer MySampleIdBlock { int mySampleId; } atomicBuffer;\n"
1377          << "layout (set=0, binding=1, std430) buffer SamplePositionsBlock { vec2 samplePositions[]; } "
1378             "positionsBuffer;\n"
1379          << "void main (void) {\n"
1380          << "    const int sampleId = atomicAdd(atomicBuffer.mySampleId, 1);\n"
1381          << "    memoryBarrier();\n"
1382          << "    const int bufferOffset = pc.sampleCount * sampleId;\n"
1383          << "    for (int idx = 0; idx < pc.sampleCount; ++idx) {\n"
1384          << "        positionsBuffer.samplePositions[bufferOffset + idx] = interpolateAtSample(inSamplePos, idx);\n"
1385          << "    }\n"
1386          << "}\n";
1387     dst.glslSources.add("frag") << glu::FragmentSource(frag.str());
1388 }
1389 
checkVaryingSamplesFragSupport(Context & context,VaryingSamplesFragParams params)1390 void checkVaryingSamplesFragSupport(Context &context, VaryingSamplesFragParams params)
1391 {
1392     const auto ctx = context.getContextCommonData();
1393 
1394     checkPipelineConstructionRequirements(ctx.vki, ctx.physicalDevice, params.constructionType);
1395     context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_FRAGMENT_STORES_AND_ATOMICS);
1396     context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
1397 
1398     // Check sample count support.
1399     const auto allowedSampleCounts = context.getDeviceProperties().limits.framebufferNoAttachmentsSampleCounts;
1400     if ((allowedSampleCounts & params.multiSampleCount) == 0u)
1401         TCU_THROW(NotSupportedError, "Requested sample count not supported");
1402 
1403     // Check for standard sample locations.
1404     if (!context.getDeviceProperties().limits.standardSampleLocations)
1405         TCU_THROW(NotSupportedError, "Standard sample locations required");
1406 }
1407 
1408 // This test creates a fragment shader pipeline library using a fragment shader that doesn't have sample shading enabled. In
1409 // addition, thanks to using dynamic rendering, no multisample information is included when creating such library. Then, the library
1410 // is included in two final pipelines: in one of them the multisample information indicates single-sample and, in the other one, it
1411 // indicates multisample.
1412 //
1413 // Then, the test runs two render loops: one for the single-sample pipeline and one for the multisample one. We expect that the
1414 // fragment shader produces the right results in both cases, even if the amount of samples was not available when the fragment
1415 // shader pipeline library was created.
1416 //
1417 // The fragment shader has been written in a way such that, when used with a single-pixel framebuffer, each invocation writes the
1418 // pixel locations of all available samples to an output buffer (note: so if 4 samples result in 4 invocations, we end up with a
1419 // maximum of 16 sample locations in the buffer). See the frag shader above.
varyingSamplesFragTest(Context & context,VaryingSamplesFragParams params)1420 tcu::TestStatus varyingSamplesFragTest(Context &context, VaryingSamplesFragParams params)
1421 {
1422     const auto &ctx = context.getContextCommonData();
1423     const tcu::IVec3 fbExtent(1, 1, 1);
1424     const auto &vkExtent    = makeExtent3D(fbExtent);
1425     const auto descType     = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
1426     const auto bindPoint    = VK_PIPELINE_BIND_POINT_GRAPHICS;
1427     const auto dataStages   = VK_SHADER_STAGE_FRAGMENT_BIT;
1428     const auto kBufferCount = 2u; // Matches frag shader: atomic buffer and positions buffer.
1429     const bool isOptimized  = (params.constructionType == PIPELINE_CONSTRUCTION_TYPE_LINK_TIME_OPTIMIZED_LIBRARY);
1430 
1431     struct PositionSampleCoords
1432     {
1433         const tcu::Vec4 position;
1434         const tcu::Vec4 sampleCoords;
1435     };
1436 
1437     // Vertices.
1438     const std::vector<PositionSampleCoords> vertices{
1439         PositionSampleCoords{tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f)},
1440         PositionSampleCoords{tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f), tcu::Vec4(0.0f, 1.0f, 0.0f, 0.0f)},
1441         PositionSampleCoords{tcu::Vec4(1.0f, -1.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f)},
1442         PositionSampleCoords{tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 1.0f, 0.0f, 0.0f)},
1443     };
1444 
1445     // Vertex buffer
1446     const auto vbSize = static_cast<VkDeviceSize>(de::dataSize(vertices));
1447     const auto vbInfo = makeBufferCreateInfo(vbSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
1448     BufferWithMemory vertexBuffer(ctx.vkd, ctx.device, ctx.allocator, vbInfo, MemoryRequirement::HostVisible);
1449     const auto vbAlloc  = vertexBuffer.getAllocation();
1450     void *vbData        = vbAlloc.getHostPtr();
1451     const auto vbOffset = static_cast<VkDeviceSize>(0);
1452 
1453     deMemcpy(vbData, de::dataOrNull(vertices), de::dataSize(vertices));
1454     flushAlloc(ctx.vkd, ctx.device, vbAlloc); // strictly speaking, not needed.
1455 
1456     // Storage buffers used in the fragment shader: atomic buffer and positions buffer.
1457     int32_t invocationCount = 0;
1458     const auto abSize       = static_cast<VkDeviceSize>(sizeof(invocationCount));
1459     const auto abInfo       = makeBufferCreateInfo(abSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
1460     BufferWithMemory atomicBuffer(ctx.vkd, ctx.device, ctx.allocator, abInfo, MemoryRequirement::HostVisible);
1461     const auto abAlloc  = atomicBuffer.getAllocation();
1462     void *abData        = abAlloc.getHostPtr();
1463     const auto abOffset = static_cast<VkDeviceSize>(0);
1464 
1465     const auto maxPositions = params.multiSampleCount * params.multiSampleCount;
1466     std::vector<tcu::Vec2> samplePositions(maxPositions, tcu::Vec2(-1.0f, -1.0f));
1467     const auto pbSize = static_cast<VkDeviceSize>(de::dataSize(samplePositions));
1468     const auto pbInfo = makeBufferCreateInfo(pbSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
1469     BufferWithMemory positionsBuffer(ctx.vkd, ctx.device, ctx.allocator, pbInfo, MemoryRequirement::HostVisible);
1470     const auto pbAlloc  = positionsBuffer.getAllocation();
1471     void *pbData        = pbAlloc.getHostPtr();
1472     const auto pbOffset = static_cast<VkDeviceSize>(0);
1473 
1474     // Descriptor pool, set, layout, etc.
1475     DescriptorPoolBuilder poolBuilder;
1476     poolBuilder.addType(descType, kBufferCount);
1477     const auto descriptorPool =
1478         poolBuilder.build(ctx.vkd, ctx.device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1479 
1480     DescriptorSetLayoutBuilder layoutBuilder;
1481     for (uint32_t i = 0u; i < kBufferCount; ++i)
1482         layoutBuilder.addSingleBinding(descType, dataStages);
1483     const auto setLayout     = layoutBuilder.build(ctx.vkd, ctx.device);
1484     const auto descriptorSet = makeDescriptorSet(ctx.vkd, ctx.device, *descriptorPool, *setLayout);
1485 
1486     DescriptorSetUpdateBuilder updateBuilder;
1487     const auto abDescInfo = makeDescriptorBufferInfo(atomicBuffer.get(), abOffset, abSize);
1488     const auto pbDescInfo = makeDescriptorBufferInfo(positionsBuffer.get(), pbOffset, pbSize);
1489     updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), descType, &abDescInfo);
1490     updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), descType, &pbDescInfo);
1491     updateBuilder.update(ctx.vkd, ctx.device);
1492 
1493     // Push constants.
1494     const auto pcSize  = static_cast<uint32_t>(sizeof(int32_t));
1495     const auto pcRange = makePushConstantRange(dataStages, 0u, pcSize);
1496 
1497     // Pipeline layout.
1498     const auto pipelineLayout = makePipelineLayout(ctx.vkd, ctx.device, *setLayout, &pcRange);
1499 
1500     // Modules.
1501     const auto &binaries  = context.getBinaryCollection();
1502     const auto vertModule = createShaderModule(ctx.vkd, ctx.device, binaries.get("vert"));
1503     const auto fragModule = createShaderModule(ctx.vkd, ctx.device, binaries.get("frag"));
1504 
1505     const std::vector<VkViewport> viewports(1u, makeViewport(vkExtent));
1506     const std::vector<VkRect2D> scissors(1u, makeRect2D(vkExtent));
1507 
1508     // Pipeline state.
1509 
1510     const auto bindingDesc = makeVertexInputBindingDescription(0u, static_cast<uint32_t>(sizeof(PositionSampleCoords)),
1511                                                                VK_VERTEX_INPUT_RATE_VERTEX);
1512 
1513     const std::vector<VkVertexInputAttributeDescription> inputAttributes{
1514         makeVertexInputAttributeDescription(0u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT,
1515                                             static_cast<uint32_t>(offsetof(PositionSampleCoords, position))),
1516         makeVertexInputAttributeDescription(1u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT,
1517                                             static_cast<uint32_t>(offsetof(PositionSampleCoords, sampleCoords))),
1518     };
1519 
1520     const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo = {
1521         VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
1522         nullptr,                                                   // const void* pNext;
1523         0u,                                                        // VkPipelineVertexInputStateCreateFlags flags;
1524         1u,                                                        // uint32_t vertexBindingDescriptionCount;
1525         &bindingDesc,                    // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
1526         de::sizeU32(inputAttributes),    // uint32_t vertexAttributeDescriptionCount;
1527         de::dataOrNull(inputAttributes), // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
1528     };
1529 
1530     const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateInfo = {
1531         VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
1532         nullptr,                                                     // const void* pNext;
1533         0u,                                                          // VkPipelineInputAssemblyStateCreateFlags flags;
1534         VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,                        // VkPrimitiveTopology topology;
1535         VK_FALSE,                                                    // VkBool32 primitiveRestartEnable;
1536     };
1537 
1538     const VkPipelineViewportStateCreateInfo viewportStateInfo = {
1539         VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
1540         nullptr,                                               // const void* pNext;
1541         0u,                                                    // VkPipelineViewportStateCreateFlags flags;
1542         de::sizeU32(viewports),                                // uint32_t viewportCount;
1543         de::dataOrNull(viewports),                             // const VkViewport* pViewports;
1544         de::sizeU32(scissors),                                 // uint32_t scissorCount;
1545         de::dataOrNull(scissors),                              // const VkRect2D* pScissors;
1546     };
1547 
1548     const VkPipelineRasterizationStateCreateInfo rasterizationStateInfo = {
1549         VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
1550         nullptr,                                                    // const void* pNext;
1551         0u,                                                         // VkPipelineRasterizationStateCreateFlags flags;
1552         VK_FALSE,                                                   // VkBool32 depthClampEnable;
1553         VK_FALSE,                                                   // VkBool32 rasterizerDiscardEnable;
1554         VK_POLYGON_MODE_FILL,                                       // VkPolygonMode polygonMode;
1555         VK_CULL_MODE_BACK_BIT,                                      // VkCullModeFlags cullMode;
1556         VK_FRONT_FACE_COUNTER_CLOCKWISE,                            // VkFrontFace frontFace;
1557         VK_FALSE,                                                   // VkBool32 depthBiasEnable;
1558         0.0f,                                                       // float depthBiasConstantFactor;
1559         0.0f,                                                       // float depthBiasClamp;
1560         0.0f,                                                       // float depthBiasSlopeFactor;
1561         1.0f,                                                       // float lineWidth;
1562     };
1563 
1564     // We will use two pipelines: one will be single-sample and the other one will be multisample.
1565     VkPipelineMultisampleStateCreateInfo multisampleStateInfo = {
1566         VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
1567         nullptr,                                                  // const void* pNext;
1568         0u,                                                       // VkPipelineMultisampleStateCreateFlags flags;
1569         params.multiSampleCount,                                  // VkSampleCountFlagBits rasterizationSamples;
1570         VK_FALSE,                                                 // VkBool32 sampleShadingEnable;
1571         1.0f,                                                     // float minSampleShading;
1572         nullptr,                                                  // const VkSampleMask* pSampleMask;
1573         VK_FALSE,                                                 // VkBool32 alphaToCoverageEnable;
1574         VK_FALSE,                                                 // VkBool32 alphaToOneEnable;
1575     };
1576 
1577     const VkPipelineDepthStencilStateCreateInfo depthStencilStateInfo = initVulkanStructure();
1578 
1579     const VkPipelineColorBlendStateCreateInfo colorBlendStateInfo = initVulkanStructure();
1580 
1581     const VkPipelineRenderingCreateInfo renderingCreateInfo = {
1582         VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO, // VkStructureType sType;
1583         nullptr,                                          // const void* pNext;
1584         0u,                                               // uint32_t viewMask;
1585         0u,                                               // uint32_t colorAttachmentCount;
1586         nullptr,                                          // const VkFormat* pColorAttachmentFormats;
1587         VK_FORMAT_UNDEFINED,                              // VkFormat depthAttachmentFormat;
1588         VK_FORMAT_UNDEFINED,                              // VkFormat stencilAttachmentFormat;
1589     };
1590 
1591     // Create a library with the vertex input state and the pre-rasterization shader state.
1592     Move<VkPipeline> preFragLib;
1593     Move<VkPipeline> fragShaderLib;
1594     Move<VkPipeline> fragOutputLibMulti;
1595     Move<VkPipeline> fragOutputLibSingle;
1596 
1597     VkPipelineCreateFlags libCreationFlags = VK_PIPELINE_CREATE_LIBRARY_BIT_KHR;
1598     VkPipelineCreateFlags linkFlags        = 0u;
1599 
1600     if (isOptimized)
1601     {
1602         libCreationFlags |= VK_PIPELINE_CREATE_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT;
1603         linkFlags |= VK_PIPELINE_CREATE_LINK_TIME_OPTIMIZATION_BIT_EXT;
1604     }
1605 
1606     // Vertex input state and pre-rasterization shader state library.
1607     {
1608         VkGraphicsPipelineLibraryCreateInfoEXT vertexInputLibInfo = initVulkanStructureConst(&renderingCreateInfo);
1609         vertexInputLibInfo.flags |= (VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT |
1610                                      VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT);
1611 
1612         VkGraphicsPipelineCreateInfo preFragPipelineInfo = initVulkanStructure(&vertexInputLibInfo);
1613         preFragPipelineInfo.flags                        = libCreationFlags;
1614         preFragPipelineInfo.pVertexInputState            = &vertexInputStateInfo;
1615         preFragPipelineInfo.pInputAssemblyState          = &inputAssemblyStateInfo;
1616 
1617         preFragPipelineInfo.layout              = pipelineLayout.get();
1618         preFragPipelineInfo.pViewportState      = &viewportStateInfo;
1619         preFragPipelineInfo.pRasterizationState = &rasterizationStateInfo;
1620 
1621         const auto vertexStageInfo = makePipelineShaderStageCreateInfo(VK_SHADER_STAGE_VERTEX_BIT, vertModule.get());
1622 
1623         preFragPipelineInfo.stageCount = 1u;
1624         preFragPipelineInfo.pStages    = &vertexStageInfo;
1625 
1626         preFragLib = createGraphicsPipeline(ctx.vkd, ctx.device, VK_NULL_HANDLE, &preFragPipelineInfo);
1627     }
1628 
1629     // Fragment shader stage library. Note we skip including multisample information here.
1630     {
1631         VkGraphicsPipelineLibraryCreateInfoEXT fragShaderLibInfo = initVulkanStructureConst(&renderingCreateInfo);
1632         fragShaderLibInfo.flags |= VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT;
1633 
1634         VkGraphicsPipelineCreateInfo fragShaderPipelineInfo = initVulkanStructure(&fragShaderLibInfo);
1635         fragShaderPipelineInfo.flags                        = libCreationFlags;
1636         fragShaderPipelineInfo.layout                       = pipelineLayout.get();
1637         fragShaderPipelineInfo.pDepthStencilState           = &depthStencilStateInfo;
1638 
1639         const auto fragStageInfo = makePipelineShaderStageCreateInfo(VK_SHADER_STAGE_FRAGMENT_BIT, fragModule.get());
1640 
1641         fragShaderPipelineInfo.stageCount = 1u;
1642         fragShaderPipelineInfo.pStages    = &fragStageInfo;
1643 
1644         fragShaderLib = createGraphicsPipeline(ctx.vkd, ctx.device, VK_NULL_HANDLE, &fragShaderPipelineInfo);
1645     }
1646 
1647     // Fragment output libraries.
1648     {
1649         VkGraphicsPipelineLibraryCreateInfoEXT fragOutputLibInfo = initVulkanStructureConst(&renderingCreateInfo);
1650         fragOutputLibInfo.flags |= VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT;
1651 
1652         VkGraphicsPipelineCreateInfo fragOutputPipelineInfo = initVulkanStructure(&fragOutputLibInfo);
1653         fragOutputPipelineInfo.flags                        = libCreationFlags;
1654         fragOutputPipelineInfo.pColorBlendState             = &colorBlendStateInfo;
1655         fragOutputPipelineInfo.pMultisampleState            = &multisampleStateInfo;
1656 
1657         fragOutputLibMulti = createGraphicsPipeline(ctx.vkd, ctx.device, VK_NULL_HANDLE, &fragOutputPipelineInfo);
1658 
1659         multisampleStateInfo.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
1660         fragOutputLibSingle = createGraphicsPipeline(ctx.vkd, ctx.device, VK_NULL_HANDLE, &fragOutputPipelineInfo);
1661     }
1662 
1663     // Linked pipelines.
1664     Move<VkPipeline> pipelineMulti;
1665     Move<VkPipeline> pipelineSingle;
1666 
1667     {
1668         const std::vector<VkPipeline> libraryHandlesMulti{
1669             preFragLib.get(),
1670             fragShaderLib.get(),
1671             fragOutputLibMulti.get(),
1672         };
1673 
1674         VkPipelineLibraryCreateInfoKHR linkedPipelineLibraryInfo = initVulkanStructure();
1675         linkedPipelineLibraryInfo.libraryCount                   = de::sizeU32(libraryHandlesMulti);
1676         linkedPipelineLibraryInfo.pLibraries                     = de::dataOrNull(libraryHandlesMulti);
1677 
1678         VkGraphicsPipelineCreateInfo linkedPipelineInfo = initVulkanStructure(&linkedPipelineLibraryInfo);
1679         linkedPipelineInfo.flags                        = linkFlags;
1680         linkedPipelineInfo.layout                       = pipelineLayout.get();
1681 
1682         pipelineMulti = createGraphicsPipeline(ctx.vkd, ctx.device, VK_NULL_HANDLE, &linkedPipelineInfo);
1683     }
1684     {
1685         const std::vector<VkPipeline> libraryHandlesSingle{
1686             preFragLib.get(),
1687             fragShaderLib.get(),
1688             fragOutputLibSingle.get(),
1689         };
1690 
1691         VkPipelineLibraryCreateInfoKHR linkedPipelineLibraryInfo = initVulkanStructure();
1692         linkedPipelineLibraryInfo.libraryCount                   = de::sizeU32(libraryHandlesSingle);
1693         linkedPipelineLibraryInfo.pLibraries                     = de::dataOrNull(libraryHandlesSingle);
1694 
1695         VkGraphicsPipelineCreateInfo linkedPipelineInfo = initVulkanStructure(&linkedPipelineLibraryInfo);
1696         linkedPipelineInfo.flags                        = linkFlags;
1697         linkedPipelineInfo.layout                       = pipelineLayout.get();
1698 
1699         pipelineSingle = createGraphicsPipeline(ctx.vkd, ctx.device, VK_NULL_HANDLE, &linkedPipelineInfo);
1700     }
1701 
1702     // Standard sample locations
1703     using LocationsVec = std::vector<tcu::Vec2>;
1704 
1705     const LocationsVec locationSamples1{
1706         tcu::Vec2(0.5f, 0.5f),
1707     };
1708 
1709     const LocationsVec locationSamples2{
1710         tcu::Vec2(0.75f, 0.75f),
1711         tcu::Vec2(0.25f, 0.25f),
1712     };
1713 
1714     const LocationsVec locationSamples4{
1715         tcu::Vec2(0.375f, 0.125f),
1716         tcu::Vec2(0.875f, 0.375f),
1717         tcu::Vec2(0.125f, 0.625f),
1718         tcu::Vec2(0.625f, 0.875f),
1719     };
1720 
1721     const LocationsVec locationSamples8{
1722         tcu::Vec2(0.5625f, 0.3125f), tcu::Vec2(0.4375f, 0.6875f), tcu::Vec2(0.8125f, 0.5625f),
1723         tcu::Vec2(0.3125f, 0.1875f), tcu::Vec2(0.1875f, 0.8125f), tcu::Vec2(0.0625f, 0.4375f),
1724         tcu::Vec2(0.6875f, 0.9375f), tcu::Vec2(0.9375f, 0.0625f),
1725     };
1726 
1727     const LocationsVec locationSamples16{
1728         tcu::Vec2(0.5625f, 0.5625f), tcu::Vec2(0.4375f, 0.3125f), tcu::Vec2(0.3125f, 0.625f),
1729         tcu::Vec2(0.75f, 0.4375f),   tcu::Vec2(0.1875f, 0.375f),  tcu::Vec2(0.625f, 0.8125f),
1730         tcu::Vec2(0.8125f, 0.6875f), tcu::Vec2(0.6875f, 0.1875f), tcu::Vec2(0.375f, 0.875f),
1731         tcu::Vec2(0.5f, 0.0625f),    tcu::Vec2(0.25f, 0.125f),    tcu::Vec2(0.125f, 0.75f),
1732         tcu::Vec2(0.0f, 0.5f),       tcu::Vec2(0.9375f, 0.25f),   tcu::Vec2(0.875f, 0.9375f),
1733         tcu::Vec2(0.0625f, 0.0f),
1734     };
1735 
1736     const auto locationThreshold = 0.00001f;
1737 
1738     const std::map<VkSampleCountFlagBits, const LocationsVec *> locationsByCount{
1739         std::make_pair(VK_SAMPLE_COUNT_1_BIT, &locationSamples1),
1740         std::make_pair(VK_SAMPLE_COUNT_2_BIT, &locationSamples2),
1741         std::make_pair(VK_SAMPLE_COUNT_4_BIT, &locationSamples4),
1742         std::make_pair(VK_SAMPLE_COUNT_8_BIT, &locationSamples8),
1743         std::make_pair(VK_SAMPLE_COUNT_16_BIT, &locationSamples16),
1744     };
1745 
1746     const VkRenderingInfo renderingInfo = {
1747         VK_STRUCTURE_TYPE_RENDERING_INFO, // VkStructureType sType;
1748         nullptr,                          // const void* pNext;
1749         0u,                               // VkRenderingFlags flags;
1750         scissors.at(0u),                  // VkRect2D renderArea;
1751         1u,                               // uint32_t layerCount;
1752         0u,                               // uint32_t viewMask;
1753         0u,                               // uint32_t colorAttachmentCount;
1754         nullptr,                          // const VkRenderingAttachmentInfo* pColorAttachments;
1755         nullptr,                          // const VkRenderingAttachmentInfo* pDepthAttachment;
1756         nullptr,                          // const VkRenderingAttachmentInfo* pStencilAttachment;
1757     };
1758 
1759     const auto hostToFragBarrier =
1760         makeMemoryBarrier(VK_ACCESS_HOST_WRITE_BIT, (VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT));
1761     const auto fragToHostBarrier = makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
1762 
1763     for (const auto multiSample : {false, true})
1764     {
1765         // Reset data in buffers.
1766         invocationCount = 0;
1767         deMemset(de::dataOrNull(samplePositions), 0, de::dataSize(samplePositions));
1768 
1769         deMemcpy(abData, &invocationCount, sizeof(invocationCount));
1770         flushAlloc(ctx.vkd, ctx.device, abAlloc);
1771 
1772         deMemcpy(pbData, de::dataOrNull(samplePositions), de::dataSize(samplePositions));
1773         flushAlloc(ctx.vkd, ctx.device, pbAlloc);
1774 
1775         CommandPoolWithBuffer cmd(ctx.vkd, ctx.device, ctx.qfIndex);
1776         const auto cmdBuffer = *cmd.cmdBuffer;
1777 
1778         const auto vkSampleCount = (multiSample ? params.multiSampleCount : VK_SAMPLE_COUNT_1_BIT);
1779         const auto sampleCount   = static_cast<int32_t>(vkSampleCount);
1780 
1781         beginCommandBuffer(ctx.vkd, cmdBuffer);
1782         cmdPipelineMemoryBarrier(ctx.vkd, cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
1783                                  &hostToFragBarrier);
1784         ctx.vkd.cmdBeginRendering(cmdBuffer, &renderingInfo);
1785         ctx.vkd.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vbOffset);
1786         ctx.vkd.cmdBindDescriptorSets(cmdBuffer, bindPoint, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, nullptr);
1787         ctx.vkd.cmdBindPipeline(cmdBuffer, bindPoint, (multiSample ? *pipelineMulti : *pipelineSingle));
1788         ctx.vkd.cmdPushConstants(cmdBuffer, *pipelineLayout, dataStages, 0u, pcSize, &sampleCount);
1789         ctx.vkd.cmdDraw(cmdBuffer, de::sizeU32(vertices), 1u, 0u, 0u);
1790         ctx.vkd.cmdEndRendering(cmdBuffer);
1791         cmdPipelineMemoryBarrier(ctx.vkd, cmdBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
1792                                  &fragToHostBarrier);
1793         endCommandBuffer(ctx.vkd, cmdBuffer);
1794         submitCommandsAndWait(ctx.vkd, ctx.device, ctx.queue, cmdBuffer);
1795 
1796         // Verify buffer contents.
1797         invalidateAlloc(ctx.vkd, ctx.device, abAlloc);
1798         invalidateAlloc(ctx.vkd, ctx.device, pbAlloc);
1799 
1800         deMemcpy(&invocationCount, abData, sizeof(invocationCount));
1801         if (invocationCount <= 0 || invocationCount > sampleCount)
1802         {
1803             const auto prefix = (multiSample ? "[MultiSample]" : "[Single-Sample]");
1804             std::ostringstream msg;
1805             msg << prefix << " Invalid invocation count found in atomic buffer: expected value in range [1, "
1806                 << sampleCount << "] but found " << invocationCount;
1807             TCU_FAIL(msg.str());
1808         }
1809 
1810         const auto itr = locationsByCount.find(vkSampleCount);
1811         DE_ASSERT(itr != locationsByCount.end());
1812         const auto expectedLocations = itr->second;
1813 
1814         deMemcpy(de::dataOrNull(samplePositions), pbData, de::dataSize(samplePositions));
1815         for (int32_t invocationIdx = 0; invocationIdx < invocationCount; ++invocationIdx)
1816         {
1817             DE_ASSERT(expectedLocations->size() == static_cast<size_t>(vkSampleCount));
1818             const auto bufferOffset = invocationIdx * sampleCount;
1819             for (int32_t sampleIdx = 0; sampleIdx < sampleCount; ++sampleIdx)
1820             {
1821                 const auto &result   = samplePositions[bufferOffset + sampleIdx];
1822                 const auto &expected = expectedLocations->at(sampleIdx);
1823 
1824                 if (!tcu::boolAll(tcu::lessThanEqual(tcu::absDiff(result, expected),
1825                                                      tcu::Vec2(locationThreshold, locationThreshold))))
1826                 {
1827                     const auto prefix = (multiSample ? "[MultiSample]" : "[Single-Sample]");
1828                     std::ostringstream msg;
1829                     msg << prefix << " Unexpected position found for invocation " << invocationIdx << " sample "
1830                         << sampleIdx << ": expected " << expected << " but found " << result;
1831                     TCU_FAIL(msg.str());
1832                 }
1833             }
1834         }
1835     }
1836 
1837     return tcu::TestStatus::pass("Pass");
1838 }
1839 
1840 class PipelineNoRenderingTestInstance : public vkt::TestInstance
1841 {
1842 public:
PipelineNoRenderingTestInstance(Context & context,const PipelineConstructionType pipelineConstructionType)1843     PipelineNoRenderingTestInstance(Context &context, const PipelineConstructionType pipelineConstructionType)
1844         : vkt::TestInstance(context)
1845         , m_pipelineConstructionType(pipelineConstructionType)
1846     {
1847     }
~PipelineNoRenderingTestInstance(void)1848     ~PipelineNoRenderingTestInstance(void)
1849     {
1850     }
1851     tcu::TestStatus iterate(void) override;
1852 
1853 private:
1854     PipelineConstructionType m_pipelineConstructionType;
1855 };
1856 
iterate()1857 tcu::TestStatus PipelineNoRenderingTestInstance::iterate()
1858 {
1859     const auto &vki       = m_context.getInstanceInterface();
1860     const auto &vkd       = m_context.getDeviceInterface();
1861     const auto physDevice = m_context.getPhysicalDevice();
1862     const auto device     = m_context.getDevice();
1863     const auto qIndex     = m_context.getUniversalQueueFamilyIndex();
1864     const auto queue      = m_context.getUniversalQueue();
1865     Allocator &alloc      = m_context.getDefaultAllocator();
1866 
1867     const auto cmdPool   = makeCommandPool(vkd, device, qIndex);
1868     const auto cmdBuffer = allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1869 
1870     const std::vector<VkViewport> viewports(1u, makeViewport(32u, 32u));
1871     const std::vector<VkRect2D> scissors(1u, makeRect2D(32u, 32u));
1872 
1873     const VkPipelineVertexInputStateCreateInfo vertexInputState     = initVulkanStructure();
1874     const VkPipelineRasterizationStateCreateInfo rasterizationState = {
1875         VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType                          sType;
1876         DE_NULL,                                                    // const void*                              pNext;
1877         (VkPipelineRasterizationStateCreateFlags)0,                 // VkPipelineRasterizationStateCreateFlags  flags;
1878         VK_FALSE,                // VkBool32                                 depthClampEnable;
1879         VK_FALSE,                // VkBool32                                 rasterizerDiscardEnable;
1880         VK_POLYGON_MODE_FILL,    // VkPolygonMode polygonMode;
1881         VK_CULL_MODE_NONE,       // VkCullModeFlags cullMode;
1882         VK_FRONT_FACE_CLOCKWISE, // VkFrontFace frontFace;
1883         VK_FALSE,                // VkBool32 depthBiasEnable;
1884         0.0f,                    // float depthBiasConstantFactor;
1885         0.0f,                    // float depthBiasClamp;
1886         0.0f,                    // float depthBiasSlopeFactor;
1887         1.0f,                    // float lineWidth;
1888     };
1889 
1890     const auto &binaries  = m_context.getBinaryCollection();
1891     const auto vertModule = ShaderWrapper(vkd, device, binaries.get("vert"));
1892     const auto fragModule = ShaderWrapper(vkd, device, binaries.get("frag"));
1893     const PipelineLayoutWrapper pipelineLayout(m_pipelineConstructionType, vkd, device);
1894 
1895     vk::GraphicsPipelineWrapper pipeline(vki, vkd, physDevice, device, m_context.getDeviceExtensions(),
1896                                          m_pipelineConstructionType);
1897     pipeline.setDefaultRasterizationState()
1898         .setupVertexInputState(&vertexInputState)
1899         .setDefaultDepthStencilState()
1900         .setDefaultMultisampleState()
1901         .setupPreRasterizationShaderState(viewports, scissors, pipelineLayout, VK_NULL_HANDLE, 0u, vertModule,
1902                                           &rasterizationState)
1903         .setupFragmentShaderState(pipelineLayout, VK_NULL_HANDLE, 0u, fragModule)
1904         .setupFragmentOutputState(VK_NULL_HANDLE)
1905         .setMonolithicPipelineLayout(pipelineLayout)
1906         .buildPipeline();
1907 
1908     auto imageExtent            = vk::makeExtent3D(32u, 32u, 1u);
1909     const auto subresourceRange = vk::makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
1910     const auto imageUsage       = static_cast<vk::VkImageUsageFlags>(vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
1911                                                                vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
1912     const vk::VkImageCreateInfo imageCreateInfo = {
1913         vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
1914         nullptr,                                 // const void* pNext;
1915         0u,                                      // VkImageCreateFlags flags;
1916         vk::VK_IMAGE_TYPE_2D,                    // VkImageType imageType;
1917         vk::VK_FORMAT_R8G8B8A8_UNORM,            // VkFormat format;
1918         imageExtent,                             // VkExtent3D extent;
1919         1u,                                      // uint32_t mipLevels;
1920         1u,                                      // uint32_t arrayLayers;
1921         vk::VK_SAMPLE_COUNT_1_BIT,               // VkSampleCountFlagBits samples;
1922         vk::VK_IMAGE_TILING_OPTIMAL,             // VkImageTiling tiling;
1923         imageUsage,                              // VkImageUsageFlags usage;
1924         vk::VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode sharingMode;
1925         1u,                                      // uint32_t queueFamilyIndexCount;
1926         &qIndex,                                 // const uint32_t* pQueueFamilyIndices;
1927         vk::VK_IMAGE_LAYOUT_UNDEFINED,           // VkImageLayout initialLayout;
1928     };
1929 
1930     auto colorAttachment = de::MovePtr<vk::ImageWithMemory>(
1931         new vk::ImageWithMemory(vkd, device, alloc, imageCreateInfo, vk::MemoryRequirement::Any));
1932     auto colorAttachmentView = vk::makeImageView(vkd, device, colorAttachment->get(), vk::VK_IMAGE_VIEW_TYPE_2D,
1933                                                  imageCreateInfo.format, subresourceRange);
1934 
1935     const auto clearValueColor = vk::makeClearValueColor(tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
1936 
1937     const vk::VkRect2D renderArea = {{0u, 0u}, {imageExtent.width, imageExtent.height}};
1938 
1939     const vk::VkRenderingAttachmentInfoKHR colorAttachments = {
1940         vk::VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR, // VkStructureType sType;
1941         nullptr,                                             // const void* pNext;
1942         colorAttachmentView.get(),                           // VkImageView imageView;
1943         vk::VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR,          // VkImageLayout imageLayout;
1944         vk::VK_RESOLVE_MODE_NONE,                            // VkResolveModeFlagBits resolveMode;
1945         VK_NULL_HANDLE,                                      // VkImageView resolveImageView;
1946         vk::VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR,          // VkImageLayout resolveImageLayout;
1947         vk::VK_ATTACHMENT_LOAD_OP_CLEAR,                     // VkAttachmentLoadOp loadOp;
1948         vk::VK_ATTACHMENT_STORE_OP_STORE,                    // VkAttachmentStoreOp storeOp;
1949         clearValueColor                                      // VkClearValue clearValue;
1950     };
1951     const VkRenderingInfoKHR render_info = {
1952         VK_STRUCTURE_TYPE_RENDERING_INFO_KHR, 0, 0, renderArea, 1, 0, 1, &colorAttachments, nullptr, nullptr};
1953 
1954     beginCommandBuffer(vkd, *cmdBuffer);
1955     vkd.cmdBeginRendering(*cmdBuffer, &render_info);
1956     pipeline.bind(*cmdBuffer);
1957     vkd.cmdDraw(*cmdBuffer, 4u, 1u, 0u, 0u);
1958     vkd.cmdEndRendering(*cmdBuffer);
1959     endCommandBuffer(vkd, *cmdBuffer);
1960     submitCommandsAndWait(vkd, device, queue, *cmdBuffer);
1961 
1962     return tcu::TestStatus::pass("Pass");
1963 }
1964 
1965 class PipelineNoRenderingTestCase : public vkt::TestCase
1966 {
1967 public:
PipelineNoRenderingTestCase(tcu::TestContext & testCtx,const std::string & name,PipelineConstructionType pipelineConstructionType)1968     PipelineNoRenderingTestCase(tcu::TestContext &testCtx, const std::string &name,
1969                                 PipelineConstructionType pipelineConstructionType)
1970         : vkt::TestCase(testCtx, name)
1971         , m_pipelineConstructionType(pipelineConstructionType)
1972     {
1973     }
~PipelineNoRenderingTestCase(void)1974     ~PipelineNoRenderingTestCase(void)
1975     {
1976     }
1977     void initPrograms(SourceCollections &programCollection) const override;
1978     void checkSupport(Context &context) const override;
1979     TestInstance *createInstance(Context &context) const override;
1980 
1981 private:
1982     const PipelineConstructionType m_pipelineConstructionType;
1983 };
1984 
createInstance(Context & context) const1985 TestInstance *PipelineNoRenderingTestCase::createInstance(Context &context) const
1986 {
1987     return new PipelineNoRenderingTestInstance(context, m_pipelineConstructionType);
1988 }
1989 
checkSupport(Context & context) const1990 void PipelineNoRenderingTestCase::checkSupport(Context &context) const
1991 {
1992     context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
1993 
1994     checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(),
1995                                           m_pipelineConstructionType);
1996 }
1997 
initPrograms(SourceCollections & sources) const1998 void PipelineNoRenderingTestCase::initPrograms(SourceCollections &sources) const
1999 {
2000     std::stringstream vert;
2001     std::stringstream frag;
2002 
2003     vert << "#version 450\n"
2004          << "void main() {\n"
2005          << "    vec2 pos = vec2(float(gl_VertexIndex & 1), float((gl_VertexIndex >> 1) & 1));\n"
2006          << "    gl_Position = vec4(pos - 0.5f, 0.0f, 1.0f);\n"
2007          << "}\n";
2008 
2009     frag << "#version 450\n"
2010          << "layout (location=0) out vec4 outColor;\n"
2011          << "void main() {\n"
2012          << "    outColor = vec4(1.0f);\n"
2013          << "}\n";
2014 
2015     sources.glslSources.add("vert") << glu::VertexSource(vert.str());
2016     sources.glslSources.add("frag") << glu::FragmentSource(frag.str());
2017 }
2018 
2019 #endif // CTS_USES_VULKANSC
2020 
2021 } // namespace
2022 
createMiscTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType)2023 tcu::TestCaseGroup *createMiscTests(tcu::TestContext &testCtx, PipelineConstructionType pipelineConstructionType)
2024 {
2025     de::MovePtr<tcu::TestCaseGroup> miscTests(new tcu::TestCaseGroup(testCtx, "misc"));
2026 
2027     // Location of the Amber script files under the data/vulkan/amber source tree.
2028     if (pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
2029         addMonolithicAmberTests(miscTests.get());
2030 
2031     // Verify implicit access to gl_PrimtiveID works
2032     miscTests->addChild(
2033         new ImplicitPrimitiveIDPassthroughCase(testCtx, "implicit_primitive_id", pipelineConstructionType, false));
2034     // Verify implicit access to gl_PrimtiveID works with a tessellation shader
2035     miscTests->addChild(new ImplicitPrimitiveIDPassthroughCase(testCtx, "implicit_primitive_id_with_tessellation",
2036                                                                pipelineConstructionType, true));
2037 
2038     if (isConstructionTypeLibrary(pipelineConstructionType))
2039     {
2040         addFunctionCaseWithPrograms(miscTests.get(), "compatible_render_pass", checkCompatibleRenderPassSupport,
2041                                     initCompatibleRenderPassPrograms, compatibleRenderPassTest,
2042                                     pipelineConstructionType);
2043     }
2044     addFunctionCaseWithPrograms(miscTests.get(), "array_of_structs_interface", checkArrayOfStructsInterfaceSupport,
2045                                 initArrayOfStructsInterfacePrograms, arrayOfStructsInterfaceTest,
2046                                 pipelineConstructionType);
2047 
2048 #ifndef CTS_USES_VULKANSC
2049     if (pipelineConstructionType == vk::PIPELINE_CONSTRUCTION_TYPE_FAST_LINKED_LIBRARY)
2050     {
2051         // Check if interpolateAtSample works as expected when using a pipeline library and null MSAA state in the fragment shader"
2052         miscTests->addChild(
2053             new PipelineLibraryInterpolateAtSampleTestCase(testCtx, "interpolate_at_sample_no_sample_shading"));
2054     }
2055 
2056     if (isConstructionTypeLibrary(pipelineConstructionType))
2057     {
2058         const VkSampleCountFlagBits sampleCounts[] = {
2059             VK_SAMPLE_COUNT_2_BIT,
2060             VK_SAMPLE_COUNT_4_BIT,
2061             VK_SAMPLE_COUNT_8_BIT,
2062             VK_SAMPLE_COUNT_16_BIT,
2063         };
2064         for (const auto sampleCount : sampleCounts)
2065         {
2066             const auto testName = "frag_lib_varying_samples_" + std::to_string(static_cast<int>(sampleCount));
2067             const VaryingSamplesFragParams params{pipelineConstructionType, sampleCount};
2068 
2069             addFunctionCaseWithPrograms(miscTests.get(), testName, checkVaryingSamplesFragSupport,
2070                                         initVaryingSamplesFragPrograms, varyingSamplesFragTest, params);
2071         }
2072     }
2073 #endif // CTS_USES_VULKANSC
2074 
2075     BindingTestConfig config0 = {pipelineConstructionType, true, false};
2076     BindingTestConfig config1 = {pipelineConstructionType, false, true};
2077     BindingTestConfig config2 = {pipelineConstructionType, true, true};
2078 
2079     // Verify implicit access to gl_PrimtiveID works with a tessellation shader
2080     miscTests->addChild(new PipelineLayoutBindingTestCases(testCtx, "descriptor_bind_test_backwards", config0));
2081     // Verify implicit access to gl_PrimtiveID works with a tessellation shader
2082     miscTests->addChild(new PipelineLayoutBindingTestCases(testCtx, "descriptor_bind_test_holes", config1));
2083     // Verify implicit access to gl_PrimtiveID works with a tessellation shader
2084     miscTests->addChild(new PipelineLayoutBindingTestCases(testCtx, "descriptor_bind_test_backwards_holes", config2));
2085 
2086 #ifndef CTS_USES_VULKANSC
2087     if (!isConstructionTypeShaderObject(pipelineConstructionType))
2088     {
2089         miscTests->addChild(new PipelineNoRenderingTestCase(testCtx, "no_rendering", pipelineConstructionType));
2090     }
2091 #endif
2092 
2093     return miscTests.release();
2094 }
2095 
2096 } // namespace pipeline
2097 } // namespace vkt
2098