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