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 ©Region);
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 ©Region);
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