1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2019 Google LLC
6 * Copyright (c) 2019 The Khronos Group Inc.
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 *
20 *//*!
21 * \file
22 * \brief Miscellaneous pipeline tests.
23 *//*--------------------------------------------------------------------*/
24
25 #include <string>
26 #include <memory>
27 #include <vector>
28 #include <algorithm>
29
30 #include "vkPipelineConstructionUtil.hpp"
31 #include "vktTestGroupUtil.hpp"
32 #include "vktAmberTestCase.hpp"
33 #include "vktPipelineMiscTests.hpp"
34
35 #include "vkDefs.hpp"
36 #include "tcuImageCompare.hpp"
37 #include "vkImageUtil.hpp"
38 #include "deStringUtil.hpp"
39 #include "vktTestCaseUtil.hpp"
40 #include "vkTypeUtil.hpp"
41 #include "vkCmdUtil.hpp"
42 #include "vkObjUtil.hpp"
43 #include "vkImageWithMemory.hpp"
44 #include "vkBarrierUtil.hpp"
45 #include "vkBufferWithMemory.hpp"
46 #include "vkBuilderUtil.hpp"
47 #include "vktPipelineReferenceRenderer.hpp"
48
49 namespace vkt
50 {
51 namespace pipeline
52 {
53
54 using namespace vk;
55
56 namespace
57 {
58
59 enum AmberFeatureBits
60 {
61 AMBER_FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS = (1 << 0),
62 AMBER_FEATURE_TESSELATION_SHADER = (1 << 1),
63 AMBER_FEATURE_GEOMETRY_SHADER = (1 << 2),
64 };
65
66 using AmberFeatureFlags = deUint32;
67
68 #ifndef CTS_USES_VULKANSC
getFeatureList(AmberFeatureFlags flags)69 std::vector<std::string> getFeatureList (AmberFeatureFlags flags)
70 {
71 std::vector<std::string> requirements;
72
73 if (flags & AMBER_FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS)
74 requirements.push_back("Features.vertexPipelineStoresAndAtomics");
75
76 if (flags & AMBER_FEATURE_TESSELATION_SHADER)
77 requirements.push_back("Features.tessellationShader");
78
79 if (flags & AMBER_FEATURE_GEOMETRY_SHADER)
80 requirements.push_back("Features.geometryShader");
81
82 return requirements;
83 }
84 #endif // CTS_USES_VULKANSC
85
addMonolithicAmberTests(tcu::TestCaseGroup * tests)86 void addMonolithicAmberTests (tcu::TestCaseGroup* tests)
87 {
88 #ifndef CTS_USES_VULKANSC
89 tcu::TestContext& testCtx = tests->getTestContext();
90
91 // Shader test files are saved in <path>/external/vulkancts/data/vulkan/amber/pipeline/<basename>.amber
92 struct Case {
93 const char* basename;
94 const char* description;
95 AmberFeatureFlags flags;
96 };
97
98 const Case cases[] =
99 {
100 {
101 "position_to_ssbo",
102 "Write position data into ssbo using only the vertex shader in a pipeline",
103 (AMBER_FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS),
104 },
105 {
106 "primitive_id_from_tess",
107 "Read primitive id from tessellation shaders without a geometry shader",
108 (AMBER_FEATURE_TESSELATION_SHADER | AMBER_FEATURE_GEOMETRY_SHADER),
109 },
110 };
111 for (unsigned i = 0; i < DE_LENGTH_OF_ARRAY(cases) ; ++i)
112 {
113 std::string file = std::string(cases[i].basename) + ".amber";
114 std::vector<std::string> requirements = getFeatureList(cases[i].flags);
115 cts_amber::AmberTestCase *testCase = cts_amber::createAmberTestCase(testCtx, cases[i].basename, cases[i].description, "pipeline", file, requirements);
116
117 tests->addChild(testCase);
118 }
119 #else
120 DE_UNREF(tests);
121 #endif
122 }
123
124 class ImplicitPrimitiveIDPassthroughCase : public vkt::TestCase
125 {
126 public:
ImplicitPrimitiveIDPassthroughCase(tcu::TestContext & testCtx,const std::string & name,const std::string & description,const PipelineConstructionType pipelineConstructionType,bool withTessellation)127 ImplicitPrimitiveIDPassthroughCase (tcu::TestContext& testCtx,
128 const std::string& name,
129 const std::string& description,
130 const PipelineConstructionType pipelineConstructionType,
131 bool withTessellation)
132 : vkt::TestCase(testCtx, name, description)
133 , m_pipelineConstructionType(pipelineConstructionType)
134 , m_withTessellationPassthrough(withTessellation)
135 {
136 }
~ImplicitPrimitiveIDPassthroughCase(void)137 ~ImplicitPrimitiveIDPassthroughCase (void) {}
138 void initPrograms (SourceCollections& programCollection) const override;
139 void checkSupport (Context& context) const override;
140 TestInstance* createInstance (Context& context) const override;
141
142 const PipelineConstructionType m_pipelineConstructionType;
143 private:
144 bool m_withTessellationPassthrough;
145 };
146
147 class ImplicitPrimitiveIDPassthroughInstance : public vkt::TestInstance
148 {
149 public:
ImplicitPrimitiveIDPassthroughInstance(Context & context,const PipelineConstructionType pipelineConstructionType,bool withTessellation)150 ImplicitPrimitiveIDPassthroughInstance (Context& context,
151 const PipelineConstructionType pipelineConstructionType,
152 bool withTessellation)
153 :
154 vkt::TestInstance(context)
155 , m_renderSize (2, 2)
156 , m_extent(makeExtent3D(m_renderSize.x(), m_renderSize.y(), 1u))
157 , m_graphicsPipeline (context.getDeviceInterface(), context.getDevice(), pipelineConstructionType)
158 , m_withTessellationPassthrough(withTessellation)
159 {
160 }
~ImplicitPrimitiveIDPassthroughInstance(void)161 ~ImplicitPrimitiveIDPassthroughInstance (void) {}
162 tcu::TestStatus iterate (void) override;
163
164 private:
165 const tcu::UVec2 m_renderSize;
166 const VkExtent3D m_extent;
167 const VkFormat m_format = VK_FORMAT_R8G8B8A8_UNORM;
168 GraphicsPipelineWrapper m_graphicsPipeline;
169 bool m_withTessellationPassthrough;
170 };
171
createInstance(Context & context) const172 TestInstance* ImplicitPrimitiveIDPassthroughCase::createInstance (Context& context) const
173 {
174 return new ImplicitPrimitiveIDPassthroughInstance(context, m_pipelineConstructionType, m_withTessellationPassthrough);
175 }
176
checkSupport(Context & context) const177 void ImplicitPrimitiveIDPassthroughCase::checkSupport (Context &context) const
178 {
179 if (m_withTessellationPassthrough)
180 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_TESSELLATION_SHADER);
181
182 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
183
184 checkPipelineLibraryRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_pipelineConstructionType);
185 }
186
initPrograms(SourceCollections & sources) const187 void ImplicitPrimitiveIDPassthroughCase::initPrograms(SourceCollections& sources) const
188 {
189 std::ostringstream vert;
190 // Generate a vertically split framebuffer, filled with red on the
191 // left, and a green on the right.
192 vert
193 << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
194 << "void main ()\n"
195 << "{\n"
196 << " switch (gl_VertexIndex) {\n"
197 << " case 0:\n"
198 << " gl_Position = vec4(-3.0, -1.0, 0.0, 1.0);\n"
199 << " break;\n"
200 << " case 1:\n"
201 << " gl_Position = vec4(0.0, 3.0, 0.0, 1.0);\n"
202 << " break;\n"
203 << " case 2:\n"
204 << " gl_Position = vec4(0.0, -1.0, 0.0, 1.0);\n"
205 << " break;\n"
206 << " case 3:\n"
207 << " gl_Position = vec4(0.0, -1.0, 0.0, 1.0);\n"
208 << " break;\n"
209 << " case 4:\n"
210 << " gl_Position = vec4(3.0, -1.0, 0.0, 1.0);\n"
211 << " break;\n"
212 << " case 5:\n"
213 << " gl_Position = vec4(0.0, 3.0, 0.0, 1.0);\n"
214 << " break;\n"
215 << " }\n"
216 << "}\n"
217 ;
218 sources.glslSources.add("vert") << glu::VertexSource(vert.str());
219
220 if (m_withTessellationPassthrough) {
221 std::ostringstream tsc;
222 tsc
223 << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
224 << "layout (vertices = 3) out;\n"
225 << "\n"
226 << "void main ()\n"
227 << "{\n"
228 << " if (gl_InvocationID == 0) {\n"
229 << " gl_TessLevelInner[0] = 1.0;\n"
230 << " gl_TessLevelInner[1] = 1.0;\n"
231 << " gl_TessLevelOuter[0] = 1.0;\n"
232 << " gl_TessLevelOuter[1] = 1.0;\n"
233 << " gl_TessLevelOuter[2] = 1.0;\n"
234 << " gl_TessLevelOuter[3] = 1.0;\n"
235 << " }\n"
236 << " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
237 << "}\n";
238 sources.glslSources.add("tsc") << glu::TessellationControlSource(tsc.str());
239
240 std::ostringstream tse;
241 tse
242 << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
243 << "layout (triangles, equal_spacing, cw) in;\n"
244 << "\n"
245 << "void main ()\n"
246 << "{\n"
247 << " gl_Position = gl_in[0].gl_Position * gl_TessCoord.x +\n"
248 << " gl_in[1].gl_Position * gl_TessCoord.y +\n"
249 << " gl_in[2].gl_Position * gl_TessCoord.z;\n"
250 << "}\n"
251 ;
252 sources.glslSources.add("tse") << glu::TessellationEvaluationSource(tse.str());
253 }
254
255 std::ostringstream frag;
256 frag
257 << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
258 << "layout (location=0) out vec4 outColor;\n"
259 << "\n"
260 << "void main ()\n"
261 << "{\n"
262 << " const vec4 red = vec4(1.0, 0.0, 0.0, 1.0);\n"
263 << " const vec4 green = vec4(0.0, 1.0, 0.0, 1.0);\n"
264 << " outColor = (gl_PrimitiveID % 2 == 0) ? red : green;\n"
265 << "}\n"
266 ;
267 sources.glslSources.add("frag") << glu::FragmentSource(frag.str());
268 }
269
iterate()270 tcu::TestStatus ImplicitPrimitiveIDPassthroughInstance::iterate ()
271 {
272 const auto& vkd = m_context.getDeviceInterface();
273 const auto device = m_context.getDevice();
274 auto& alloc = m_context.getDefaultAllocator();
275 const auto qIndex = m_context.getUniversalQueueFamilyIndex();
276 const auto queue = m_context.getUniversalQueue();
277 const auto tcuFormat = mapVkFormat(m_format);
278 const auto colorUsage = (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
279 const auto verifBufferUsage = VK_BUFFER_USAGE_TRANSFER_DST_BIT;
280 const tcu::Vec4 clearColor (0.0f, 0.0f, 0.0f, 1.0f);
281
282 // Color attachment.
283 const VkImageCreateInfo colorBufferInfo =
284 {
285 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
286 nullptr, // const void* pNext;
287 0u, // VkImageCreateFlags flags;
288 VK_IMAGE_TYPE_2D, // VkImageType imageType;
289 m_format, // VkFormat format;
290 m_extent, // VkExtent3D extent;
291 1u, // uint32_t mipLevels;
292 1u, // uint32_t arrayLayers;
293 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
294 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
295 colorUsage, // VkImageUsageFlags usage;
296 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
297 0u, // uint32_t queueFamilyIndexCount;
298 nullptr, // const uint32_t* pQueueFamilyIndices;
299 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
300 };
301 ImageWithMemory colorBuffer (vkd, device, alloc, colorBufferInfo, MemoryRequirement::Any);
302 const auto colorSRR = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
303 const auto colorSRL = makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
304 const auto colorBufferView = makeImageView(vkd, device, colorBuffer.get(), VK_IMAGE_VIEW_TYPE_2D, m_format, colorSRR);
305
306 // Verification buffer.
307 const auto verifBufferSize = static_cast<VkDeviceSize>(tcu::getPixelSize(tcuFormat)) * m_extent.width * m_extent.height;
308 const auto verifBufferInfo = makeBufferCreateInfo(verifBufferSize, verifBufferUsage);
309 BufferWithMemory verifBuffer (vkd, device, alloc, verifBufferInfo, MemoryRequirement::HostVisible);
310 auto& verifBufferAlloc = verifBuffer.getAllocation();
311
312 // Render pass and framebuffer.
313 const auto renderPass = makeRenderPass(vkd, device, m_format);
314 const auto framebuffer = makeFramebuffer(vkd, device, renderPass.get(), colorBufferView.get(), m_extent.width, m_extent.height);
315
316 // Shader modules.
317 const auto& binaries = m_context.getBinaryCollection();
318 const auto vertModule = createShaderModule(vkd, device, binaries.get("vert"));
319 const auto fragModule = createShaderModule(vkd, device, binaries.get("frag"));
320 Move<VkShaderModule> tscModule;
321 Move<VkShaderModule> tseModule;
322
323 if (m_withTessellationPassthrough) {
324 tscModule = createShaderModule(vkd, device, binaries.get("tsc"));
325 tseModule = createShaderModule(vkd, device, binaries.get("tse"));
326 }
327
328 // Viewports and scissors.
329 const std::vector<VkViewport> viewports (1u, makeViewport(m_extent));
330 const std::vector<VkRect2D> scissors (1u, makeRect2D(m_extent));
331
332 const VkPipelineVertexInputStateCreateInfo vertexInputState = initVulkanStructure();
333 const VkPipelineRasterizationStateCreateInfo rasterizationState =
334 {
335 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
336 DE_NULL, // const void* pNext;
337 (VkPipelineRasterizationStateCreateFlags)0, // VkPipelineRasterizationStateCreateFlags flags;
338 VK_FALSE, // VkBool32 depthClampEnable;
339 VK_FALSE, // VkBool32 rasterizerDiscardEnable;
340 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode;
341 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode;
342 VK_FRONT_FACE_CLOCKWISE, // VkFrontFace frontFace;
343 VK_FALSE, // VkBool32 depthBiasEnable;
344 0.0f, // float depthBiasConstantFactor;
345 0.0f, // float depthBiasClamp;
346 0.0f, // float depthBiasSlopeFactor;
347 1.0f, // float lineWidth;
348 };
349
350 // Pipeline layout and graphics pipeline.
351 const auto pipelineLayout = makePipelineLayout(vkd, device);
352
353 const auto topology = m_withTessellationPassthrough ? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST : VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
354 m_graphicsPipeline.setDefaultRasterizationState()
355 .setDefaultTopology(topology)
356 .setupVertexInputState(&vertexInputState)
357 .setDefaultDepthStencilState()
358 .setDefaultMultisampleState()
359 .setDefaultColorBlendState()
360 .setupPreRasterizationShaderState(viewports, scissors, *pipelineLayout, *renderPass, 0u, *vertModule, &rasterizationState, *tscModule, *tseModule)
361 .setupFragmentShaderState(*pipelineLayout, *renderPass, 0u, *fragModule)
362 .setupFragmentOutputState(*renderPass)
363 .setMonolithicPipelineLayout(*pipelineLayout)
364 .buildPipeline();
365
366 // Command pool and buffer.
367 const auto cmdPool = makeCommandPool(vkd, device, qIndex);
368 const auto cmdBufferPtr = allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
369 const auto cmdBuffer = cmdBufferPtr.get();
370
371 beginCommandBuffer(vkd, cmdBuffer);
372
373 // Draw.
374 beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffer.get(), scissors.at(0u), clearColor);
375 vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_graphicsPipeline.getPipeline());
376 vkd.cmdDraw(cmdBuffer, 6, 1u, 0u, 0u);
377 endRenderPass(vkd, cmdBuffer);
378
379 // Copy to verification buffer.
380 const auto copyRegion = makeBufferImageCopy(m_extent, colorSRL);
381 const auto transfer2Host = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
382 const auto color2Transfer = makeImageMemoryBarrier(
383 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
384 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
385 colorBuffer.get(), colorSRR);
386
387 cmdPipelineImageMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, &color2Transfer);
388 vkd.cmdCopyImageToBuffer(cmdBuffer, colorBuffer.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, verifBuffer.get(), 1u, ©Region);
389 cmdPipelineMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, &transfer2Host);
390
391 endCommandBuffer(vkd, cmdBuffer);
392
393 // Submit and validate result.
394 submitCommandsAndWait(vkd, device, queue, cmdBuffer);
395
396 auto& log = m_context.getTestContext().getLog();
397 const tcu::IVec3 iExtent (static_cast<int>(m_extent.width), static_cast<int>(m_extent.height), static_cast<int>(m_extent.depth));
398 void* verifBufferData = verifBufferAlloc.getHostPtr();
399 const tcu::ConstPixelBufferAccess verifAccess (tcuFormat, iExtent, verifBufferData);
400 invalidateAlloc(vkd, device, verifBufferAlloc);
401
402 const auto red = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
403 const auto green = tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f);
404
405 for (int x = 0; x < iExtent.x(); ++x)
406 for (int y = 0; y < iExtent.y(); ++y) {
407 const auto resultColor = verifAccess.getPixel(x, y);
408 const auto expectedColor = (x < iExtent.x() / 2) ? red : green;
409 if (resultColor != expectedColor) {
410 log << tcu::TestLog::ImageSet("Result image", "Expect left side of framebuffer red, and right side green")
411 << tcu::TestLog::Image("Result", "Verification buffer", verifAccess)
412 << tcu::TestLog::EndImageSet;
413 TCU_FAIL("Expected a vertically split framebuffer, filled with red on the left and green the right; see the log for the unexpected result");
414 }
415 }
416
417 return tcu::TestStatus::pass("Pass");
418 }
419
420 #ifndef CTS_USES_VULKANSC
421 struct UnusedShaderStageParams
422 {
423 PipelineConstructionType pipelineConstructionType;
424 bool useTessShaders;
425 bool useGeomShader;
426 };
427
428 class UnusedShaderStagesCase : public vkt::TestCase
429 {
430 public:
UnusedShaderStagesCase(tcu::TestContext & testCtx,const std::string & name,const std::string & description,const UnusedShaderStageParams & params)431 UnusedShaderStagesCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const UnusedShaderStageParams& params)
432 : vkt::TestCase (testCtx, name, description)
433 , m_params (params)
434 {}
~UnusedShaderStagesCase(void)435 virtual ~UnusedShaderStagesCase (void) {}
436
437 void initPrograms (vk::SourceCollections& programCollection) const override;
438 TestInstance* createInstance (Context& context) const override;
439 void checkSupport (Context& context) const override;
440
441 protected:
442 UnusedShaderStageParams m_params;
443 };
444
445 class UnusedShaderStagesInstance : public vkt::TestInstance
446 {
447 public:
UnusedShaderStagesInstance(Context & context,const UnusedShaderStageParams & params)448 UnusedShaderStagesInstance (Context& context, const UnusedShaderStageParams& params)
449 : vkt::TestInstance (context)
450 , m_params (params)
451 {}
~UnusedShaderStagesInstance(void)452 virtual ~UnusedShaderStagesInstance (void) {}
453 tcu::TestStatus iterate (void) override;
454
455 protected:
456 UnusedShaderStageParams m_params;
457 };
458
initPrograms(vk::SourceCollections & programCollection) const459 void UnusedShaderStagesCase::initPrograms (vk::SourceCollections &programCollection) const
460 {
461 // Shaders that produce bad results.
462 {
463 std::ostringstream vert;
464 vert
465 << "#version 460\n"
466 << "out gl_PerVertex {\n"
467 << " vec4 gl_Position;\n"
468 << "};\n"
469 << "void main (void) {\n"
470 << " gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n"
471 << "}\n"
472 ;
473 programCollection.glslSources.add("bad_vert") << glu::VertexSource(vert.str());
474
475 std::ostringstream tesc;
476 tesc
477 << "#version 460\n"
478 << "layout (vertices=3) out;\n"
479 << "in gl_PerVertex {\n"
480 << " vec4 gl_Position;\n"
481 << "} gl_in[gl_MaxPatchVertices];\n"
482 << "out gl_PerVertex {\n"
483 << " vec4 gl_Position;\n"
484 << "} gl_out[];\n"
485 << "void main (void) {\n"
486 << " gl_TessLevelInner[0] = 1.0;\n"
487 << " gl_TessLevelInner[1] = 1.0;\n"
488 << " gl_TessLevelOuter[0] = 1.0;\n"
489 << " gl_TessLevelOuter[1] = 1.0;\n"
490 << " gl_TessLevelOuter[2] = 1.0;\n"
491 << " gl_TessLevelOuter[3] = 1.0;\n"
492 << " gl_out[gl_InvocationID].gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n"
493 << "}\n"
494 ;
495 programCollection.glslSources.add("bad_tesc") << glu::TessellationControlSource(tesc.str());
496
497 std::ostringstream tese;
498 tese
499 << "#version 460\n"
500 << "layout (triangles, fractional_odd_spacing, cw) in;\n"
501 << "in gl_PerVertex {\n"
502 << " vec4 gl_Position;\n"
503 << "} gl_in[gl_MaxPatchVertices];\n"
504 << "out gl_PerVertex {\n"
505 << " vec4 gl_Position;\n"
506 << "};\n"
507 << "void main() {\n"
508 << " gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n"
509 << "}\n"
510 ;
511 programCollection.glslSources.add("bad_tese") << glu::TessellationEvaluationSource(tese.str());
512
513 std::ostringstream geom;
514 geom
515 << "#version 460\n"
516 << "layout (triangles) in;\n"
517 << "layout (triangle_strip, max_vertices=3) out;\n"
518 << "in gl_PerVertex {\n"
519 << " vec4 gl_Position;\n"
520 << "} gl_in[3];\n"
521 << "out gl_PerVertex {\n"
522 << " vec4 gl_Position;\n"
523 << "};\n"
524 << "void main() {\n"
525 // Avoid emitting any vertices.
526 << "}\n"
527 ;
528 programCollection.glslSources.add("bad_geom") << glu::GeometrySource(geom.str());
529
530 std::ostringstream frag;
531 frag
532 << "#version 460\n"
533 << "layout (location=0) out vec4 outColor;\n"
534 << "void main (void) {\n"
535 << " outColor = vec4(0.0, 0.0, 0.0, 1.0);\n"
536 << "}\n"
537 ;
538 programCollection.glslSources.add("bad_frag") << glu::FragmentSource(frag.str());
539 }
540
541 // Shaders that produce the expected results.
542 {
543 std::ostringstream vert;
544 vert
545 << "#version 460\n"
546 << "out gl_PerVertex {\n"
547 << " vec4 gl_Position;\n"
548 << "};\n"
549 << "vec2 positions[3] = vec2[](\n"
550 << " vec2(-1.0, -1.0),\n"
551 << " vec2(-1.0, 3.0),\n"
552 << " vec2( 3.0, -1.0)\n"
553 << ");\n"
554 << "void main (void) {\n"
555 << " gl_Position = vec4(positions[gl_VertexIndex % 3], 0.0, 1.0);\n"
556 << "}\n"
557 ;
558 programCollection.glslSources.add("vert") << glu::VertexSource(vert.str());
559
560 std::ostringstream tesc;
561 tesc
562 << "#version 460\n"
563 << "layout (vertices=3) out;\n"
564 << "in gl_PerVertex {\n"
565 << " vec4 gl_Position;\n"
566 << "} gl_in[gl_MaxPatchVertices];\n"
567 << "out gl_PerVertex {\n"
568 << " vec4 gl_Position;\n"
569 << "} gl_out[];\n"
570 << "void main (void) {\n"
571 << " gl_TessLevelInner[0] = 1.0;\n"
572 << " gl_TessLevelInner[1] = 1.0;\n"
573 << " gl_TessLevelOuter[0] = 1.0;\n"
574 << " gl_TessLevelOuter[1] = 1.0;\n"
575 << " gl_TessLevelOuter[2] = 1.0;\n"
576 << " gl_TessLevelOuter[3] = 1.0;\n"
577 << " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
578 << "}\n"
579 ;
580 programCollection.glslSources.add("tesc") << glu::TessellationControlSource(tesc.str());
581
582 std::ostringstream tese;
583 tese
584 << "#version 460\n"
585 << "layout (triangles, fractional_odd_spacing, cw) in;\n"
586 << "in gl_PerVertex {\n"
587 << " vec4 gl_Position;\n"
588 << "} gl_in[gl_MaxPatchVertices];\n"
589 << "out gl_PerVertex {\n"
590 << " vec4 gl_Position;\n"
591 << "};\n"
592 << "void main() {\n"
593 << " gl_Position = (gl_TessCoord.x * gl_in[0].gl_Position) +\n"
594 << " (gl_TessCoord.y * gl_in[1].gl_Position) +\n"
595 << " (gl_TessCoord.z * gl_in[2].gl_Position);\n"
596 << "}\n"
597 ;
598 programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(tese.str());
599
600 std::ostringstream geom;
601 geom
602 << "#version 460\n"
603 << "layout (triangles) in;\n"
604 << "layout (triangle_strip, max_vertices=3) out;\n"
605 << "in gl_PerVertex {\n"
606 << " vec4 gl_Position;\n"
607 << "} gl_in[3];\n"
608 << "out gl_PerVertex {\n"
609 << " vec4 gl_Position;\n"
610 << "};\n"
611 << "void main() {\n"
612 << " gl_Position = gl_in[0].gl_Position; EmitVertex();\n"
613 << " gl_Position = gl_in[1].gl_Position; EmitVertex();\n"
614 << " gl_Position = gl_in[2].gl_Position; EmitVertex();\n"
615 << "}\n"
616 ;
617 programCollection.glslSources.add("geom") << glu::GeometrySource(geom.str());
618
619 std::ostringstream frag;
620 frag
621 << "#version 460\n"
622 << "layout (location=0) out vec4 outColor;\n"
623 << "void main (void) {\n"
624 << " outColor = vec4(0.0, 1.0, 0.0, 1.0);\n" // Blue instead of black.
625 << "}\n"
626 ;
627 programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
628 }
629 }
630
createInstance(Context & context) const631 TestInstance* UnusedShaderStagesCase::createInstance (Context &context) const
632 {
633 return new UnusedShaderStagesInstance(context, m_params);
634 }
635
checkSupport(Context & context) const636 void UnusedShaderStagesCase::checkSupport (Context &context) const
637 {
638 checkPipelineLibraryRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_params.pipelineConstructionType);
639
640 if (m_params.useTessShaders)
641 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_TESSELLATION_SHADER);
642
643 if (m_params.useGeomShader)
644 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
645 }
646
makePipelineShaderStageCreateInfo(VkShaderStageFlagBits stage,VkShaderModule module)647 VkPipelineShaderStageCreateInfo makePipelineShaderStageCreateInfo (VkShaderStageFlagBits stage, VkShaderModule module)
648 {
649 const VkPipelineShaderStageCreateInfo stageInfo =
650 {
651 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
652 nullptr, // const void* pNext;
653 0u, // VkPipelineShaderStageCreateFlags flags;
654 stage, // VkShaderStageFlagBits stage;
655 module, // VkShaderModule module;
656 "main", // const char* pName;
657 nullptr, // const VkSpecializationInfo* pSpecializationInfo;
658 };
659 return stageInfo;
660 }
661
iterate()662 tcu::TestStatus UnusedShaderStagesInstance::iterate ()
663 {
664 const auto& vkd = m_context.getDeviceInterface();
665 const auto device = m_context.getDevice();
666 auto& alloc = m_context.getDefaultAllocator();
667 const auto queue = m_context.getUniversalQueue();
668 const auto queueIndex = m_context.getUniversalQueueFamilyIndex();
669
670 const bool isOptimized = (m_params.pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_LINK_TIME_OPTIMIZED_LIBRARY);
671 const auto colorExtent = makeExtent3D(1u, 1u, 1u);
672 const tcu::IVec3 colorExtentVec (static_cast<int>(colorExtent.width), static_cast<int>(colorExtent.height), static_cast<int>(colorExtent.depth));
673 const auto colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
674 const auto colorUsage = (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
675 const auto colorSRR = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
676 const auto colorSRL = makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
677 const auto tcuFormat = mapVkFormat(colorFormat);
678 const tcu::Vec4 clearColor (0.0f, 0.0f, 0.0f, 0.0f);
679 const tcu::Vec4 expectedColor (0.0f, 1.0f, 0.0f, 1.0f); // Must match the good frag shader.
680
681 // Good and bad shader modules.
682 const auto& binaries = m_context.getBinaryCollection();
683
684 const auto goodVertModule = createShaderModule(vkd, device, binaries.get("vert"));
685 const auto goodTescModule = (m_params.useTessShaders ? createShaderModule(vkd, device, binaries.get("tesc")) : Move<VkShaderModule>());
686 const auto goodTeseModule = (m_params.useTessShaders ? createShaderModule(vkd, device, binaries.get("tese")) : Move<VkShaderModule>());
687 const auto goodGeomModule = (m_params.useGeomShader ? createShaderModule(vkd, device, binaries.get("geom")) : Move<VkShaderModule>());
688 const auto goodFragModule = createShaderModule(vkd, device, binaries.get("frag"));
689
690 const auto goodVertShaderInfo = makePipelineShaderStageCreateInfo(VK_SHADER_STAGE_VERTEX_BIT, goodVertModule.get());
691 const auto goodTescShaderInfo = makePipelineShaderStageCreateInfo(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, goodTescModule.get());
692 const auto goodTeseShaderInfo = makePipelineShaderStageCreateInfo(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, goodTeseModule.get());
693 const auto goodGeomShaderInfo = makePipelineShaderStageCreateInfo(VK_SHADER_STAGE_GEOMETRY_BIT, goodGeomModule.get());
694 const auto goodFragShaderInfo = makePipelineShaderStageCreateInfo(VK_SHADER_STAGE_FRAGMENT_BIT, goodFragModule.get());
695
696 const auto badVertModule = createShaderModule(vkd, device, binaries.get("bad_vert"));
697 const auto badTescModule = (m_params.useTessShaders ? createShaderModule(vkd, device, binaries.get("bad_tesc")) : Move<VkShaderModule>());
698 const auto badTeseModule = (m_params.useTessShaders ? createShaderModule(vkd, device, binaries.get("bad_tese")) : Move<VkShaderModule>());
699 const auto badGeomModule = (m_params.useGeomShader ? createShaderModule(vkd, device, binaries.get("bad_geom")) : Move<VkShaderModule>());
700 const auto badFragModule = createShaderModule(vkd, device, binaries.get("bad_frag"));
701
702 const auto badVertShaderInfo = makePipelineShaderStageCreateInfo(VK_SHADER_STAGE_VERTEX_BIT, badVertModule.get());
703 const auto badTescShaderInfo = makePipelineShaderStageCreateInfo(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, badTescModule.get());
704 const auto badTeseShaderInfo = makePipelineShaderStageCreateInfo(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, badTeseModule.get());
705 const auto badGeomShaderInfo = makePipelineShaderStageCreateInfo(VK_SHADER_STAGE_GEOMETRY_BIT, badGeomModule.get());
706 const auto badFragShaderInfo = makePipelineShaderStageCreateInfo(VK_SHADER_STAGE_FRAGMENT_BIT, badFragModule.get());
707
708 // Color attachment.
709 const VkImageCreateInfo colorAttachmentCreateInfo =
710 {
711 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
712 nullptr, // const void* pNext;
713 0u, // VkImageCreateFlags flags;
714 VK_IMAGE_TYPE_2D, // VkImageType imageType;
715 colorFormat, // VkFormat format;
716 colorExtent, // VkExtent3D extent;
717 1u, // uint32_t mipLevels;
718 1u, // uint32_t arrayLayers;
719 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
720 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
721 colorUsage, // VkImageUsageFlags usage;
722 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
723 0u, // uint32_t queueFamilyIndexCount;
724 nullptr, // const uint32_t* pQueueFamilyIndices;
725 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
726 };
727 ImageWithMemory colorAttachment (vkd, device, alloc, colorAttachmentCreateInfo, MemoryRequirement::Any);
728
729 // Color attachment view.
730 const auto colorAttachmentView = makeImageView(vkd, device, colorAttachment.get(), VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSRR);
731
732 // Verification buffer.
733 const auto verificationBufferSize = static_cast<VkDeviceSize>(tcu::getPixelSize(tcuFormat)) * colorExtent.width * colorExtent.height * colorExtent.depth;
734 const auto verificationBufferCreateInfo = makeBufferCreateInfo(verificationBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
735 BufferWithMemory verificationBuffer (vkd, device, alloc, verificationBufferCreateInfo, MemoryRequirement::HostVisible);
736 auto& verificationBufferAlloc = verificationBuffer.getAllocation();
737
738 // Render pass and framebuffer.
739 const auto renderPass = makeRenderPass(vkd, device, colorFormat);
740 const auto framebuffer = makeFramebuffer(vkd, device, renderPass.get(), colorAttachmentView.get(), colorExtent.width, colorExtent.height);
741
742 // Pipeline layout.
743 const auto pipelineLayout = makePipelineLayout(vkd, device);
744
745 // Pipeline state.
746
747 const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo = initVulkanStructure();
748
749 const auto primitiveTopology = (m_params.useTessShaders ? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST : VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST);
750
751 const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateInfo =
752 {
753 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
754 nullptr, // const void* pNext;
755 0u, // VkPipelineInputAssemblyStateCreateFlags flags;
756 primitiveTopology, // VkPrimitiveTopology topology;
757 VK_FALSE, // VkBool32 primitiveRestartEnable;
758 };
759
760 const VkPipelineTessellationStateCreateInfo tessellationStateInfo =
761 {
762 VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, // VkStructureType sType;
763 nullptr, // const void* pNext;
764 0u, // VkPipelineTessellationStateCreateFlags flags;
765 3u, // uint32_t patchControlPoints;
766 };
767
768 const std::vector<VkViewport> viewports (1u, makeViewport(colorExtent));
769 const std::vector<VkRect2D> scissors (1u, makeRect2D(colorExtent));
770
771 const VkPipelineViewportStateCreateInfo viewportStateInfo =
772 {
773 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
774 nullptr, // const void* pNext;
775 0u, // VkPipelineViewportStateCreateFlags flags;
776 de::sizeU32(viewports), // uint32_t viewportCount;
777 de::dataOrNull(viewports), // const VkViewport* pViewports;
778 de::sizeU32(scissors), // uint32_t scissorCount;
779 de::dataOrNull(scissors), // const VkRect2D* pScissors;
780 };
781
782 const VkPipelineRasterizationStateCreateInfo rasterizationStateInfo =
783 {
784 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
785 nullptr, // const void* pNext;
786 0u, // VkPipelineRasterizationStateCreateFlags flags;
787 VK_FALSE, // VkBool32 depthClampEnable;
788 VK_FALSE, // VkBool32 rasterizerDiscardEnable;
789 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode;
790 VK_CULL_MODE_BACK_BIT, // VkCullModeFlags cullMode;
791 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
792 VK_FALSE, // VkBool32 depthBiasEnable;
793 0.0f, // float depthBiasConstantFactor;
794 0.0f, // float depthBiasClamp;
795 0.0f, // float depthBiasSlopeFactor;
796 1.0f, // float lineWidth;
797 };
798
799 const VkPipelineMultisampleStateCreateInfo multisampleStateInfo =
800 {
801 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
802 nullptr, // const void* pNext;
803 0u, // VkPipelineMultisampleStateCreateFlags flags;
804 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
805 VK_FALSE, // VkBool32 sampleShadingEnable;
806 1.0f, // float minSampleShading;
807 nullptr, // const VkSampleMask* pSampleMask;
808 VK_FALSE, // VkBool32 alphaToCoverageEnable;
809 VK_FALSE, // VkBool32 alphaToOneEnable;
810 };
811
812 const VkPipelineDepthStencilStateCreateInfo depthStencilStateInfo = initVulkanStructure();
813
814 const VkColorComponentFlags colorComponentFlags = (VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT);
815
816 const VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
817 {
818 VK_FALSE, // VkBool32 blendEnable;
819 VK_BLEND_FACTOR_ZERO, // VkBlendFactor srcColorBlendFactor;
820 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor;
821 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp;
822 VK_BLEND_FACTOR_ZERO, // VkBlendFactor srcAlphaBlendFactor;
823 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor;
824 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp;
825 colorComponentFlags, // VkColorComponentFlags colorWriteMask;
826 };
827
828 const VkPipelineColorBlendStateCreateInfo colorBlendStateInfo =
829 {
830 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
831 nullptr, // const void* pNext;
832 0u, // VkPipelineColorBlendStateCreateFlags flags;
833 VK_FALSE, // VkBool32 logicOpEnable;
834 VK_LOGIC_OP_CLEAR, // VkLogicOp logicOp;
835 1u, // uint32_t attachmentCount;
836 &colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments;
837 { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConstants[4];
838 };
839
840 // Make a few vectors with the wrong shader modules.
841 std::vector<VkPipelineShaderStageCreateInfo> badPreRasterStages;
842 badPreRasterStages.push_back(badVertShaderInfo);
843 if (m_params.useTessShaders)
844 {
845 badPreRasterStages.push_back(badTescShaderInfo);
846 badPreRasterStages.push_back(badTeseShaderInfo);
847 }
848 if (m_params.useGeomShader)
849 badPreRasterStages.push_back(badGeomShaderInfo);
850
851 std::vector<VkPipelineShaderStageCreateInfo> allBadStages (badPreRasterStages);
852 allBadStages.push_back(badFragShaderInfo);
853
854 // Make a few vectors with the right shader modules.
855 std::vector<VkPipelineShaderStageCreateInfo> goodPreRasterStages;
856 goodPreRasterStages.push_back(goodVertShaderInfo);
857 if (m_params.useTessShaders)
858 {
859 goodPreRasterStages.push_back(goodTescShaderInfo);
860 goodPreRasterStages.push_back(goodTeseShaderInfo);
861 }
862 if (m_params.useGeomShader)
863 goodPreRasterStages.push_back(goodGeomShaderInfo);
864
865 std::vector<VkPipelineShaderStageCreateInfo> allGoodStages (goodPreRasterStages);
866 allGoodStages.push_back(goodFragShaderInfo);
867
868 // Build the different pipeline pieces.
869 Move<VkPipeline> vertexInputLib;
870 Move<VkPipeline> preRasterShaderLib;
871 Move<VkPipeline> fragShaderLib;
872 Move<VkPipeline> fragOutputLib;
873
874 VkPipelineCreateFlags libCreationFlags = VK_PIPELINE_CREATE_LIBRARY_BIT_KHR;
875 VkPipelineCreateFlags linkFlags = 0u;
876
877 if (isOptimized)
878 {
879 libCreationFlags |= VK_PIPELINE_CREATE_RETAIN_LINK_TIME_OPTIMIZATION_INFO_BIT_EXT;
880 linkFlags |= VK_PIPELINE_CREATE_LINK_TIME_OPTIMIZATION_BIT_EXT;
881 }
882
883 // Vertex input state library.
884 {
885 VkGraphicsPipelineLibraryCreateInfoEXT vertexInputLibInfo = initVulkanStructure();
886 vertexInputLibInfo.flags |= VK_GRAPHICS_PIPELINE_LIBRARY_VERTEX_INPUT_INTERFACE_BIT_EXT;
887
888 VkGraphicsPipelineCreateInfo vertexInputPipelineInfo = initVulkanStructure(&vertexInputLibInfo);
889 vertexInputPipelineInfo.flags = libCreationFlags;
890 vertexInputPipelineInfo.pVertexInputState = &vertexInputStateInfo;
891 vertexInputPipelineInfo.pInputAssemblyState = &inputAssemblyStateInfo;
892
893 // Add all bad shaders (they should be ignored).
894 vertexInputPipelineInfo.stageCount = de::sizeU32(allBadStages);
895 vertexInputPipelineInfo.pStages = de::dataOrNull(allBadStages);
896
897 vertexInputLib = createGraphicsPipeline(vkd, device, DE_NULL, &vertexInputPipelineInfo);
898 }
899
900 // Pre-rasterization shader state library.
901 {
902 VkGraphicsPipelineLibraryCreateInfoEXT preRasterShaderLibInfo = initVulkanStructure();
903 preRasterShaderLibInfo.flags |= VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT;
904
905 VkGraphicsPipelineCreateInfo preRasterShaderPipelineInfo = initVulkanStructure(&preRasterShaderLibInfo);
906 preRasterShaderPipelineInfo.flags = libCreationFlags;
907 preRasterShaderPipelineInfo.layout = pipelineLayout.get();
908 preRasterShaderPipelineInfo.pViewportState = &viewportStateInfo;
909 preRasterShaderPipelineInfo.pRasterizationState = &rasterizationStateInfo;
910 if (m_params.useTessShaders)
911 {
912 preRasterShaderPipelineInfo.pInputAssemblyState = &inputAssemblyStateInfo;
913 preRasterShaderPipelineInfo.pTessellationState = &tessellationStateInfo;
914 }
915 preRasterShaderPipelineInfo.renderPass = renderPass.get();
916
917 // All good pre-rasterization stages.
918 auto preRasterStagesVec = goodPreRasterStages;
919 // The bad fragment shader state cannot be added here due to VUID-VkGraphicsPipelineCreateInfo-pStages-06894.
920 //preRasterStagesVec.push_back(badFragShaderInfo);
921
922 preRasterShaderPipelineInfo.stageCount = de::sizeU32(preRasterStagesVec);
923 preRasterShaderPipelineInfo.pStages = de::dataOrNull(preRasterStagesVec);
924
925 preRasterShaderLib = createGraphicsPipeline(vkd, device, DE_NULL, &preRasterShaderPipelineInfo);
926 }
927
928 // Fragment shader stage library.
929 {
930 VkGraphicsPipelineLibraryCreateInfoEXT fragShaderLibInfo = initVulkanStructure();
931 fragShaderLibInfo.flags |= VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT;
932
933 VkGraphicsPipelineCreateInfo fragShaderPipelineInfo = initVulkanStructure(&fragShaderLibInfo);
934 fragShaderPipelineInfo.flags = libCreationFlags;
935 fragShaderPipelineInfo.layout = pipelineLayout.get();
936 fragShaderPipelineInfo.pMultisampleState = &multisampleStateInfo;
937 fragShaderPipelineInfo.pDepthStencilState = &depthStencilStateInfo;
938 fragShaderPipelineInfo.renderPass = renderPass.get();
939
940 // The good fragment shader stage.
941 std::vector<VkPipelineShaderStageCreateInfo> fragShaderStagesVec;
942 // We cannot add the bad pre-rasterization shader stages due to VUID-VkGraphicsPipelineCreateInfo-pStages-06895.
943 //fragShaderStagesVec.insert(fragShaderStagesVec.end(), badPreRasterStages.begin(), badPreRasterStages.end())
944 fragShaderStagesVec.push_back(goodFragShaderInfo);
945
946 fragShaderPipelineInfo.stageCount = de::sizeU32(fragShaderStagesVec);
947 fragShaderPipelineInfo.pStages = de::dataOrNull(fragShaderStagesVec);
948
949 fragShaderLib = createGraphicsPipeline(vkd, device, DE_NULL, &fragShaderPipelineInfo);
950 }
951
952 // Fragment output library.
953 {
954 VkGraphicsPipelineLibraryCreateInfoEXT fragOutputLibInfo = initVulkanStructure();
955 fragOutputLibInfo.flags |= VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT;
956
957 VkGraphicsPipelineCreateInfo fragOutputPipelineInfo = initVulkanStructure(&fragOutputLibInfo);
958 fragOutputPipelineInfo.flags = libCreationFlags;
959 fragOutputPipelineInfo.pColorBlendState = &colorBlendStateInfo;
960 fragOutputPipelineInfo.renderPass = renderPass.get();
961 fragOutputPipelineInfo.pMultisampleState = &multisampleStateInfo;
962
963 // Add all bad shaders (they should be ignored).
964 fragOutputPipelineInfo.stageCount = de::sizeU32(allBadStages);
965 fragOutputPipelineInfo.pStages = de::dataOrNull(allBadStages);
966
967 fragOutputLib = createGraphicsPipeline(vkd, device, DE_NULL, &fragOutputPipelineInfo);
968 }
969
970 // Linked pipeline.
971 const std::vector<VkPipeline> libraryHandles
972 {
973 vertexInputLib.get(),
974 preRasterShaderLib.get(),
975 fragShaderLib.get(),
976 fragOutputLib.get(),
977 };
978
979 VkPipelineLibraryCreateInfoKHR linkedPipelineLibraryInfo = initVulkanStructure();
980 linkedPipelineLibraryInfo.libraryCount = de::sizeU32(libraryHandles);
981 linkedPipelineLibraryInfo.pLibraries = de::dataOrNull(libraryHandles);
982
983 VkGraphicsPipelineCreateInfo linkedPipelineInfo = initVulkanStructure(&linkedPipelineLibraryInfo);
984 linkedPipelineInfo.flags = linkFlags;
985 linkedPipelineInfo.layout = pipelineLayout.get();
986 linkedPipelineInfo.stageCount = de::sizeU32(allBadStages);
987 linkedPipelineInfo.pStages = de::dataOrNull(allBadStages);
988
989 const auto pipeline = createGraphicsPipeline(vkd, device, DE_NULL, &linkedPipelineInfo);
990
991 // Command pool, command buffer and draw.
992 const auto cmdPool = makeCommandPool(vkd, device, queueIndex);
993 const auto cmdBufferPtr = allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
994 const auto cmdBuffer = cmdBufferPtr.get();
995
996 beginCommandBuffer(vkd, cmdBuffer);
997 beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffer.get(), scissors.at(0u), clearColor);
998 vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get());
999 vkd.cmdDraw(cmdBuffer, 3u, 1u, 0u, 0u);
1000 endRenderPass(vkd, cmdBuffer);
1001
1002 // Copy color attachment to verification buffer.
1003 const auto preCopyBarrier = makeImageMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
1004 VK_ACCESS_TRANSFER_READ_BIT,
1005 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
1006 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1007 colorAttachment.get(), colorSRR);
1008 const auto copyRegion = makeBufferImageCopy(colorExtent, colorSRL);
1009 const auto postCopyBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
1010
1011 cmdPipelineImageMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, &preCopyBarrier);
1012 vkd.cmdCopyImageToBuffer(cmdBuffer, colorAttachment.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, verificationBuffer.get(), 1u, ©Region);
1013 cmdPipelineMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, &postCopyBarrier);
1014
1015 endCommandBuffer(vkd, cmdBuffer);
1016
1017 submitCommandsAndWait(vkd, device, queue, cmdBuffer);
1018
1019 // Verify pixel contents.
1020 invalidateAlloc(vkd, device, verificationBufferAlloc);
1021 tcu::PixelBufferAccess resultAccess (tcuFormat, colorExtentVec, verificationBufferAlloc.getHostPtr());
1022
1023 for (int z = 0; z < colorExtentVec.z(); ++z)
1024 for (int y = 0; y < colorExtentVec.y(); ++y)
1025 for (int x = 0; x < colorExtentVec.x(); ++x)
1026 {
1027 const auto resultColor = resultAccess.getPixel(x, y, z);
1028 if (resultColor != expectedColor)
1029 {
1030 const tcu::IVec3 position(x, y, z);
1031 std::ostringstream msg;
1032 msg << "Bad color found at pixel " << position << ": expected " << expectedColor << " but found " << resultColor;
1033 TCU_FAIL(msg.str());
1034 }
1035 }
1036
1037 return tcu::TestStatus::pass("Pass");
1038 }
1039 #endif // CTS_USES_VULKANSC
1040
1041 #ifndef CTS_USES_VULKANSC
1042 class PipelineLibraryInterpolateAtSampleTestCase : public vkt::TestCase
1043 {
1044 public:
1045 PipelineLibraryInterpolateAtSampleTestCase(tcu::TestContext& context, const std::string& name, const std::string& description);
1046 void initPrograms (vk::SourceCollections& programCollection) const override;
1047 TestInstance* createInstance (Context& context) const override;
1048 void checkSupport (Context& context) const override;
1049 //there are 4 sample points, which may have a shader invocation each, each of them writes 5 values
1050 //and we render a 2x2 grid.
1051 static constexpr uint32_t width = 2;
1052 static constexpr uint32_t height = 2;
1053 static constexpr VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_4_BIT;
1054 static constexpr uint32_t ResultCount = (sampleCount + 1) * sampleCount * width * height;
1055 };
1056
1057 class PipelineLibraryInterpolateAtSampleTestInstance : public vkt::TestInstance
1058 {
1059 public:
1060 PipelineLibraryInterpolateAtSampleTestInstance(Context& context);
1061 void runTest(BufferWithMemory& index, BufferWithMemory& values, size_t bufferSize, PipelineConstructionType type);
1062 virtual tcu::TestStatus iterate(void);
1063 };
1064
PipelineLibraryInterpolateAtSampleTestCase(tcu::TestContext & context,const std::string & name,const std::string & description)1065 PipelineLibraryInterpolateAtSampleTestCase::PipelineLibraryInterpolateAtSampleTestCase(tcu::TestContext& context, const std::string& name, const std::string& description):
1066 vkt::TestCase(context, name, description) { }
1067
checkSupport(Context & context) const1068 void PipelineLibraryInterpolateAtSampleTestCase::checkSupport(Context& context) const
1069 {
1070 context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
1071 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_FRAGMENT_STORES_AND_ATOMICS);
1072 checkPipelineLibraryRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), vk::PIPELINE_CONSTRUCTION_TYPE_FAST_LINKED_LIBRARY);
1073 }
1074
initPrograms(vk::SourceCollections & collection) const1075 void PipelineLibraryInterpolateAtSampleTestCase::initPrograms(vk::SourceCollections& collection) const
1076 {
1077 {
1078 std::ostringstream src;
1079 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1080 << "vec2 positions[6] = vec2[](\n"
1081 << " vec2(1.0, 1.0),"
1082 << " vec2(-1.0, 1.0),"
1083 << " vec2(-1.0, -1.0),"
1084 << " vec2(-1.0, -1.0),"
1085 << " vec2(1.0, -1.0),"
1086 << " vec2(1.0, 1.0)"
1087 << ");\n"
1088 << "float values[6] = {0.1, 0.2, 0.3, 0.4, 0.5, 0.6};\n"
1089 << "layout (location=0) out float verify;"
1090 << "void main() {\n"
1091 << " gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);\n"
1092 << " verify = values[gl_VertexIndex];\n"
1093 << "}";
1094 collection.glslSources.add("vert") << glu::VertexSource(src.str());
1095 }
1096
1097 {
1098 std::ostringstream src;
1099 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1100 << "layout(location = 0) out vec4 outColor;\n"
1101 << "layout (location=0) in float verify;"
1102 << "layout(std430, binding = 0) buffer Index {"
1103 << " uint writeIndex;"
1104 << "} index;\n"
1105 << "layout(std430, binding = 1) buffer Values {"
1106 << " float num[" << PipelineLibraryInterpolateAtSampleTestCase::ResultCount << "];"
1107 << "} values;\n"
1108 << "void main() {\n"
1109 << " uint index = atomicAdd(index.writeIndex, 5);"
1110 << " float iSample1 = interpolateAtSample(verify, 0);\n"
1111 << " float iSample2 = interpolateAtSample(verify, 1);\n"
1112 << " float iSample3 = interpolateAtSample(verify, 2);\n"
1113 << " float iSample4 = interpolateAtSample(verify, 3);\n"
1114 << " values.num[index] = verify;"
1115 << " values.num[index + 1] = iSample1;"
1116 << " values.num[index + 2] = iSample2;"
1117 << " values.num[index + 3] = iSample3;"
1118 << " values.num[index + 4] = iSample4;"
1119 << " outColor = vec4(1.0, 1.0, 0.0, 1.0);\n"
1120 << "}";
1121 collection.glslSources.add("frag") << glu::FragmentSource(src.str());
1122 }
1123 }
1124
createInstance(Context & context) const1125 TestInstance* PipelineLibraryInterpolateAtSampleTestCase::createInstance(Context& context) const
1126 {
1127 return new PipelineLibraryInterpolateAtSampleTestInstance(context);
1128 }
1129
PipelineLibraryInterpolateAtSampleTestInstance(Context & context)1130 PipelineLibraryInterpolateAtSampleTestInstance::PipelineLibraryInterpolateAtSampleTestInstance(Context& context) : vkt::TestInstance(context) { }
1131
runTest(BufferWithMemory & index,BufferWithMemory & values,size_t bufferSize,PipelineConstructionType type)1132 void PipelineLibraryInterpolateAtSampleTestInstance::runTest(BufferWithMemory& index, BufferWithMemory& values, size_t bufferSize, PipelineConstructionType type)
1133 {
1134 const auto& vkd = m_context.getDeviceInterface();
1135 const auto device = m_context.getDevice();
1136 auto& alloc = m_context.getDefaultAllocator();
1137 auto imageFormat = vk::VK_FORMAT_R8G8B8A8_UNORM;
1138 auto imageExtent = vk::makeExtent3D(2, 2, 1u);
1139
1140 const std::vector<vk::VkViewport> viewports { makeViewport(imageExtent) };
1141 const std::vector<vk::VkRect2D> scissors { makeRect2D(imageExtent) };
1142
1143 de::MovePtr<vk::ImageWithMemory> colorAttachment;
1144
1145 vk::GraphicsPipelineWrapper pipeline1(vkd, device, type);
1146 const auto qIndex = m_context.getUniversalQueueFamilyIndex();
1147
1148 const auto subresourceRange = vk::makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
1149 const auto imageUsage = static_cast<vk::VkImageUsageFlags>(vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
1150 const vk::VkImageCreateInfo imageCreateInfo =
1151 {
1152 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
1153 nullptr, // const void* pNext;
1154 0u, // VkImageCreateFlags flags;
1155 vk::VK_IMAGE_TYPE_2D, // VkImageType imageType;
1156 imageFormat, // VkFormat format;
1157 imageExtent, // VkExtent3D extent;
1158 1u, // deUint32 mipLevels;
1159 1u, // deUint32 arrayLayers;
1160 vk::VK_SAMPLE_COUNT_4_BIT, // VkSampleCountFlagBits samples;
1161 vk::VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
1162 imageUsage, // VkImageUsageFlags usage;
1163 vk::VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1164 1u, // deUint32 queueFamilyIndexCount;
1165 &qIndex, // const deUint32* pQueueFamilyIndices;
1166 vk::VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
1167 };
1168
1169 colorAttachment = de::MovePtr<vk::ImageWithMemory>(new vk::ImageWithMemory(vkd, device, alloc, imageCreateInfo, vk::MemoryRequirement::Any));
1170 auto colorAttachmentView = vk::makeImageView(vkd, device, colorAttachment->get(), vk::VK_IMAGE_VIEW_TYPE_2D, imageFormat, subresourceRange);
1171
1172 vk::DescriptorSetLayoutBuilder layoutBuilder;
1173 layoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT);
1174 layoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT);
1175
1176 auto descriptorSetLayout = layoutBuilder.build(vkd, device);
1177 auto graphicsPipelineLayout = vk::makePipelineLayout(vkd, device, descriptorSetLayout.get());
1178
1179 DescriptorPoolBuilder poolBuilder;
1180 poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
1181 poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
1182 const auto descriptorPool = poolBuilder.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
1183 const auto descriptorSetBuffer = makeDescriptorSet(vkd, device, descriptorPool.get(), descriptorSetLayout.get());
1184
1185 // Update descriptor sets.
1186 DescriptorSetUpdateBuilder updater;
1187
1188 const auto indexBufferInfo = makeDescriptorBufferInfo(index.get(), 0ull, sizeof(uint32_t));
1189 const auto valueBufferInfo = makeDescriptorBufferInfo(values.get(), 0ull, bufferSize);
1190 updater.writeSingle(descriptorSetBuffer.get(), DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &indexBufferInfo);
1191 updater.writeSingle(descriptorSetBuffer.get(), DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &valueBufferInfo);
1192
1193 updater.update(vkd, device);
1194
1195 auto vtxshader = vk::createShaderModule(vkd, device, m_context.getBinaryCollection().get("vert"));
1196 auto frgshader = vk::createShaderModule(vkd, device, m_context.getBinaryCollection().get("frag"));
1197
1198 const vk::VkPipelineVertexInputStateCreateInfo vertexInputState =
1199 {
1200 vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType
1201 nullptr, // const void* pNext
1202 0u, // VkPipelineVertexInputStateCreateFlags flags
1203 0u, // deUint32 vertexBindingDescriptionCount
1204 nullptr, // const VkVertexInputBindingDescription* pVertexBindingDescriptions
1205 0u, // deUint32 vertexAttributeDescriptionCount
1206 nullptr, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions
1207 };
1208
1209 VkPipelineMultisampleStateCreateInfo multisampling = initVulkanStructure();
1210 multisampling.sampleShadingEnable = VK_FALSE;
1211 multisampling.rasterizationSamples = VK_SAMPLE_COUNT_4_BIT;
1212 multisampling.minSampleShading = 1.0f; // Optional
1213 multisampling.pSampleMask = NULL; // Optional
1214 multisampling.alphaToCoverageEnable = VK_FALSE; // Optional
1215 multisampling.alphaToOneEnable = VK_FALSE; // Optional
1216
1217 pipeline1.setDefaultTopology(vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
1218 .setDefaultRasterizationState()
1219 .setDefaultDepthStencilState()
1220 .setDefaultColorBlendState()
1221 .setupVertexInputState(&vertexInputState)
1222 .setupPreRasterizationShaderState(
1223 viewports,
1224 scissors,
1225 *graphicsPipelineLayout,
1226 DE_NULL,
1227 0u,
1228 *vtxshader)
1229 .setupFragmentShaderState(*graphicsPipelineLayout, DE_NULL, 0u,
1230 *frgshader)
1231 .setupFragmentOutputState(DE_NULL, 0u, DE_NULL, &multisampling)
1232 .setMonolithicPipelineLayout(*graphicsPipelineLayout).buildPipeline();
1233
1234 auto commandPool = createCommandPool(vkd, device, vk::VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, qIndex);
1235 auto commandBuffer = vk::allocateCommandBuffer(vkd, device, commandPool.get(), vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1236
1237 const auto clearValueColor = vk::makeClearValueColor(tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
1238
1239 const vk::VkRect2D renderArea =
1240 {
1241 { 0u, 0u },
1242 { imageExtent.width, imageExtent.height }
1243 };
1244
1245 const vk::VkRenderingAttachmentInfoKHR colorAttachments = {
1246 vk::VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR, // VkStructureType sType;
1247 DE_NULL, // const void* pNext;
1248 colorAttachmentView.get(), // VkImageView imageView;
1249 vk::VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR, // VkImageLayout imageLayout;
1250 vk::VK_RESOLVE_MODE_NONE, // VkResolveModeFlagBits resolveMode;
1251 DE_NULL, // VkImageView resolveImageView;
1252 vk::VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR, // VkImageLayout resolveImageLayout;
1253 vk::VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
1254 vk::VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
1255 clearValueColor // VkClearValue clearValue;
1256 };
1257 const VkRenderingInfoKHR render_info = {
1258 VK_STRUCTURE_TYPE_RENDERING_INFO_KHR,
1259 0,
1260 0,
1261 renderArea,
1262 1,
1263 0,
1264 1,
1265 &colorAttachments,
1266 DE_NULL,
1267 DE_NULL
1268 };
1269
1270 vk::beginCommandBuffer(vkd, commandBuffer.get());
1271 vk::VkImageMemoryBarrier initialBarrier = makeImageMemoryBarrier(0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR,
1272 (*colorAttachment).get(), subresourceRange);
1273 vkd.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0, nullptr,
1274 0, nullptr, 1, &initialBarrier);
1275 vkd.cmdBindDescriptorSets(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipelineLayout.get(), 0u, 1, &descriptorSetBuffer.get(), 0u, nullptr);
1276
1277 vkd.cmdBeginRendering(*commandBuffer, &render_info);
1278 vkd.cmdBindPipeline(commandBuffer.get(), vk::VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline1.getPipeline());
1279 vkd.cmdDraw(commandBuffer.get(), 6, 1, 0, 0);
1280 vkd.cmdEndRendering(*commandBuffer);
1281
1282 const VkBufferMemoryBarrier indexBufferBarrier = makeBufferMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, index.get(), 0ull, sizeof(uint32_t));
1283 vkd.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
1284 0u, 0, nullptr, 1, &indexBufferBarrier, 0, nullptr);
1285
1286 const VkBufferMemoryBarrier valueBufferBarrier = makeBufferMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, values.get(), 0ull, bufferSize);
1287 vkd.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
1288 0u, 0, nullptr, 1, &valueBufferBarrier, 0, nullptr);
1289
1290 vk::endCommandBuffer(vkd, commandBuffer.get());
1291 vk::submitCommandsAndWait(vkd, device, m_context.getUniversalQueue(), commandBuffer.get());
1292 }
1293
iterate(void)1294 tcu::TestStatus PipelineLibraryInterpolateAtSampleTestInstance::iterate(void)
1295 {
1296 const auto& vkd = m_context.getDeviceInterface();
1297 const auto device = m_context.getDevice();
1298 auto& alloc = m_context.getDefaultAllocator();
1299
1300 struct ValueBuffer {
1301 float values[PipelineLibraryInterpolateAtSampleTestCase::ResultCount];
1302 };
1303
1304 size_t resultSize = PipelineLibraryInterpolateAtSampleTestCase::ResultCount;
1305
1306 const auto indexBufferSize = static_cast<VkDeviceSize>(sizeof(uint32_t));
1307 const auto valueBufferSize = static_cast<VkDeviceSize>(sizeof(ValueBuffer));
1308
1309 auto indexCreateInfo = makeBufferCreateInfo(indexBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
1310 auto valuesCreateInfo = makeBufferCreateInfo(valueBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
1311
1312 BufferWithMemory indexBufferMonolithic (vkd, device, alloc, indexCreateInfo, MemoryRequirement::HostVisible);
1313 BufferWithMemory valuesBufferMonolithic (vkd, device, alloc, valuesCreateInfo, MemoryRequirement::HostVisible);
1314 BufferWithMemory indexBufferGPL (vkd, device, alloc, indexCreateInfo, MemoryRequirement::HostVisible);
1315 BufferWithMemory valuesBufferGPL (vkd, device, alloc, valuesCreateInfo, MemoryRequirement::HostVisible);
1316
1317 auto& indexBufferMonolithicAlloc = indexBufferMonolithic.getAllocation();
1318 auto& valuesBufferMonolithicAlloc = valuesBufferMonolithic.getAllocation();
1319 auto& indexBufferGPLAlloc = indexBufferGPL.getAllocation();
1320 auto& valuesBufferGPLAlloc = valuesBufferGPL.getAllocation();
1321
1322 void* indexBufferMonolithicData = indexBufferMonolithicAlloc.getHostPtr();
1323 void* valuesBufferMonolithicData = valuesBufferMonolithicAlloc.getHostPtr();
1324 void* indexBufferGPLData = indexBufferGPLAlloc.getHostPtr();
1325 void* valuesBufferGPLData = valuesBufferGPLAlloc.getHostPtr();
1326
1327 deMemset(indexBufferMonolithicData, 0, sizeof(uint32_t));
1328 deMemset(valuesBufferMonolithicData, 0, sizeof(ValueBuffer));
1329 deMemset(indexBufferGPLData, 0, sizeof(uint32_t));
1330 deMemset(valuesBufferGPLData, 0, sizeof(ValueBuffer));
1331
1332 flushAlloc(vkd, device, indexBufferMonolithicAlloc);
1333 flushAlloc(vkd, device, valuesBufferMonolithicAlloc);
1334 flushAlloc(vkd, device, indexBufferGPLAlloc);
1335 flushAlloc(vkd, device, valuesBufferGPLAlloc);
1336
1337 runTest(indexBufferMonolithic, valuesBufferMonolithic, valueBufferSize, vk::PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC);
1338 runTest(indexBufferGPL, valuesBufferGPL, valueBufferSize, vk::PIPELINE_CONSTRUCTION_TYPE_FAST_LINKED_LIBRARY);
1339
1340 invalidateAlloc(vkd, device, indexBufferMonolithicAlloc);
1341 invalidateAlloc(vkd, device, valuesBufferMonolithicAlloc);
1342 invalidateAlloc(vkd, device, indexBufferGPLAlloc);
1343 invalidateAlloc(vkd, device, valuesBufferGPLAlloc);
1344
1345 uint32_t monolithicIndex;
1346 uint32_t GPLIndex;
1347 struct ValueBuffer monolithicResult = ValueBuffer();
1348 struct ValueBuffer GPLResult = ValueBuffer();
1349 memcpy((void*)&monolithicIndex, indexBufferMonolithicData, sizeof(uint32_t));
1350 memcpy((void*)&GPLIndex, indexBufferGPLData, sizeof(uint32_t));
1351 memcpy((void*)&monolithicResult, valuesBufferMonolithicData, sizeof(ValueBuffer));
1352 memcpy((void*)&GPLResult, valuesBufferGPLData, sizeof(ValueBuffer));
1353
1354 //we can't know which order the shaders will run in
1355 std::sort(monolithicResult.values, monolithicResult.values + resultSize);
1356 std::sort(GPLResult.values, GPLResult.values + resultSize);
1357
1358 //check that the atomic counters are at enough for the number of invocations
1359 constexpr int expected = (PipelineLibraryInterpolateAtSampleTestCase::sampleCount + 1) *
1360 PipelineLibraryInterpolateAtSampleTestCase::width * PipelineLibraryInterpolateAtSampleTestCase::height;
1361
1362 if (monolithicIndex < expected && GPLIndex < expected) {
1363 return tcu::TestStatus::fail("Atomic counter value lower than expected");
1364 }
1365
1366 for (uint32_t i = 1; i < PipelineLibraryInterpolateAtSampleTestCase::ResultCount; i++) {
1367 if (monolithicResult.values[i] != monolithicResult.values[i]) {
1368 return tcu::TestStatus::fail("Comparison failed");
1369 }
1370 }
1371
1372 return tcu::TestStatus::pass("Pass");
1373 }
1374 #endif
1375
1376 } // anonymous
1377
1378
createMiscTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType)1379 tcu::TestCaseGroup* createMiscTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType)
1380 {
1381 de::MovePtr<tcu::TestCaseGroup> miscTests (new tcu::TestCaseGroup(testCtx, "misc", ""));
1382
1383 // Location of the Amber script files under the data/vulkan/amber source tree.
1384 if (pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
1385 addMonolithicAmberTests(miscTests.get());
1386
1387 miscTests->addChild(new ImplicitPrimitiveIDPassthroughCase(testCtx, "implicit_primitive_id", "Verify implicit access to gl_PrimtiveID works", pipelineConstructionType, false));
1388 miscTests->addChild(new ImplicitPrimitiveIDPassthroughCase(testCtx, "implicit_primitive_id_with_tessellation", "Verify implicit access to gl_PrimtiveID works with a tessellation shader", pipelineConstructionType, true));
1389 #ifndef CTS_USES_VULKANSC
1390 if (pipelineConstructionType == vk::PIPELINE_CONSTRUCTION_TYPE_FAST_LINKED_LIBRARY) {
1391 miscTests->addChild(new PipelineLibraryInterpolateAtSampleTestCase(testCtx, "interpolate_at_sample_no_sample_shading", "Check if interpolateAtSample works as expected when using a pipeline library and null MSAA state in the fragment shader"));
1392 }
1393 #endif
1394
1395 #ifndef CTS_USES_VULKANSC
1396 if (pipelineConstructionType != PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
1397 {
1398 for (int useTessIdx = 0; useTessIdx < 2; ++useTessIdx)
1399 for (int useGeomIdx = 0; useGeomIdx < 2; ++useGeomIdx)
1400 {
1401 const bool useTess = (useTessIdx > 0);
1402 const bool useGeom = (useGeomIdx > 0);
1403
1404 std::string testName = "unused_shader_stages";
1405
1406 if (useTess)
1407 testName += "_include_tess";
1408
1409 if (useGeom)
1410 testName += "_include_geom";
1411
1412 const UnusedShaderStageParams params { pipelineConstructionType, useTess, useGeom };
1413 miscTests->addChild(new UnusedShaderStagesCase(testCtx, testName, "", params));
1414 }
1415 }
1416 #endif // CTS_USES_VULKANSC
1417
1418 return miscTests.release();
1419 }
1420
1421 } // pipeline
1422 } // vkt
1423