1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2019 The Khronos Group Inc.
6 * Copyright (c) 2019 Valve Corporation.
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 * \brief Pipeline Cache Tests
23 *//*--------------------------------------------------------------------*/
25 #include "vktPipelineCreationFeedbackTests.hpp"
26 #include "vktPipelineVertexUtil.hpp"
27 #include "vktTestCase.hpp"
28 #include "vktTestCaseUtil.hpp"
29 #include "vkMemUtil.hpp"
30 #include "vkBuilderUtil.hpp"
31 #include "vkRefUtil.hpp"
32 #include "vkTypeUtil.hpp"
33 #include "vkObjUtil.hpp"
34 #include "tcuTestLog.hpp"
50 VK_MAX_SHADER_STAGES = 6,
55 PIPELINE_CACHE_NDX_NO_CACHE = 0,
56 PIPELINE_CACHE_NDX_DERIVATIVE = 1,
57 PIPELINE_CACHE_NDX_CACHED = 2,
58 PIPELINE_CACHE_NDX_COUNT,
63 std::string getShaderFlagStr (const VkShaderStageFlagBits shader,
66 std::ostringstream desc;
69 case VK_SHADER_STAGE_VERTEX_BIT:
71 desc << ((isDescription) ? "vertex stage" : "vertex_stage");
74 case VK_SHADER_STAGE_FRAGMENT_BIT:
76 desc << ((isDescription) ? "fragment stage" : "fragment_stage");
79 case VK_SHADER_STAGE_GEOMETRY_BIT:
81 desc << ((isDescription) ? "geometry stage" : "geometry_stage");
84 case VK_SHADER_STAGE_COMPUTE_BIT:
86 desc << ((isDescription) ? "compute stage" : "compute_stage");
89 case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
91 desc << ((isDescription) ? "tessellation control stage" : "tessellation_control_stage");
94 case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
96 desc << ((isDescription) ? "tessellation evaluation stage" : "tessellation_evaluation_stage");
100 desc << "unknown shader stage!";
101 DE_FATAL("Unknown shader Stage!");
108 std::string getCaseStr (const deUint32 ndx)
110 std::ostringstream desc;
113 case PIPELINE_CACHE_NDX_NO_CACHE:
115 desc << "No cached pipeline";
118 case PIPELINE_CACHE_NDX_CACHED:
120 desc << "Cached pipeline";
123 case PIPELINE_CACHE_NDX_DERIVATIVE:
125 desc << "Pipeline derivative";
129 desc << "Unknown case";
130 DE_FATAL("Unknown case!");
141 CacheTestParam (const VkShaderStageFlagBits* shaders,
144 deBool delayedDestroy);
145 virtual ~CacheTestParam (void);
146 virtual const std::string generateTestName (void) const;
147 virtual const std::string generateTestDescription (void) const;
148 VkShaderStageFlagBits getShaderFlag (deUint32 ndx) const { return m_shaders[ndx]; }
149 deUint32 getShaderCount (void) const { return (deUint32)m_shaderCount; }
150 deBool isCacheDisabled (void) const { return m_noCache; }
151 deBool isDelayedDestroy (void) const { return m_delayedDestroy; }
154 VkShaderStageFlagBits m_shaders[VK_MAX_SHADER_STAGES];
155 size_t m_shaderCount;
157 bool m_delayedDestroy;
160 CacheTestParam::CacheTestParam (const VkShaderStageFlagBits* shaders, deUint32 count, deBool noCache, deBool delayedDestroy)
162 DE_ASSERT(count <= VK_MAX_SHADER_STAGES);
163 for (deUint32 ndx = 0; ndx < count; ndx++)
164 m_shaders[ndx] = shaders[ndx];
165 m_shaderCount = count;
167 m_delayedDestroy = delayedDestroy;
170 CacheTestParam::~CacheTestParam (void)
174 const std::string CacheTestParam::generateTestName (void) const
176 std::string result(getShaderFlagStr(m_shaders[0], false));
177 std::string cacheString [] = { "", "_no_cache" };
178 std::string delayedDestroyString [] = { "", "_delayed_destroy" };
180 for(deUint32 ndx = 1; ndx < m_shaderCount; ndx++)
181 result += '_' + getShaderFlagStr(m_shaders[ndx], false) + cacheString[m_noCache ? 1 : 0] + delayedDestroyString[m_delayedDestroy ? 1 : 0];
183 if (m_shaderCount == 1)
184 result += cacheString[m_noCache ? 1 : 0] + delayedDestroyString[m_delayedDestroy ? 1 : 0];
189 const std::string CacheTestParam::generateTestDescription (void) const
191 std::string result("Get pipeline creation feedback with " + getShaderFlagStr(m_shaders[0], true));
193 result += " with no cache";
194 if (m_delayedDestroy)
195 result += " with delayed destroy";
197 for(deUint32 ndx = 1; ndx < m_shaderCount; ndx++)
198 result += ' ' + getShaderFlagStr(m_shaders[ndx], true);
203 class SimpleGraphicsPipelineBuilder
206 SimpleGraphicsPipelineBuilder (Context& context);
207 ~SimpleGraphicsPipelineBuilder (void) { }
208 void bindShaderStage (VkShaderStageFlagBits stage,
209 const char* sourceName,
210 const char* entryName);
211 void enableTessellationStage (deUint32 patchControlPoints);
212 VkPipeline buildPipeline (tcu::UVec2 renderSize,
213 VkRenderPass renderPass,
214 VkPipelineCache cache,
215 VkPipelineLayout pipelineLayout,
216 VkPipelineCreationFeedbackEXT *pipelineCreationFeedback,
217 VkPipelineCreationFeedbackEXT *pipelineStageCreationFeedbacks,
218 VkPipeline basePipelineHandle);
219 void resetBuilder (void);
224 Move<VkShaderModule> m_shaderModules[VK_MAX_SHADER_STAGES];
225 deUint32 m_shaderStageCount;
226 VkPipelineShaderStageCreateInfo m_shaderStageInfo[VK_MAX_SHADER_STAGES];
228 deUint32 m_patchControlPoints;
231 SimpleGraphicsPipelineBuilder::SimpleGraphicsPipelineBuilder (Context& context)
234 m_patchControlPoints = 0;
235 m_shaderStageCount = 0;
238 void SimpleGraphicsPipelineBuilder::resetBuilder (void)
240 m_shaderStageCount = 0;
243 void SimpleGraphicsPipelineBuilder::bindShaderStage (VkShaderStageFlagBits stage,
244 const char* sourceName,
245 const char* entryName)
247 const DeviceInterface& vk = m_context.getDeviceInterface();
248 const VkDevice vkDevice = m_context.getDevice();
250 // Create shader module
251 deUint32* code = (deUint32*)m_context.getBinaryCollection().get(sourceName).getBinary();
252 deUint32 codeSize = (deUint32)m_context.getBinaryCollection().get(sourceName).getSize();
254 const VkShaderModuleCreateInfo moduleCreateInfo =
256 VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, // VkStructureType sType;
257 DE_NULL, // const void* pNext;
258 0u, // VkShaderModuleCreateFlags flags;
259 codeSize, // deUintptr codeSize;
260 code, // const deUint32* pCode;
263 m_shaderModules[m_shaderStageCount] = createShaderModule(vk, vkDevice, &moduleCreateInfo);
265 // Prepare shader stage info
266 m_shaderStageInfo[m_shaderStageCount].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
267 m_shaderStageInfo[m_shaderStageCount].pNext = DE_NULL;
268 m_shaderStageInfo[m_shaderStageCount].flags = 0u;
269 m_shaderStageInfo[m_shaderStageCount].stage = stage;
270 m_shaderStageInfo[m_shaderStageCount].module = *m_shaderModules[m_shaderStageCount];
271 m_shaderStageInfo[m_shaderStageCount].pName = entryName;
272 m_shaderStageInfo[m_shaderStageCount].pSpecializationInfo = DE_NULL;
274 m_shaderStageCount++;
277 VkPipeline SimpleGraphicsPipelineBuilder::buildPipeline (tcu::UVec2 renderSize, VkRenderPass renderPass, VkPipelineCache cache,
278 VkPipelineLayout pipelineLayout, VkPipelineCreationFeedbackEXT *pipelineCreationFeedback,
279 VkPipelineCreationFeedbackEXT *pipelineStageCreationFeedbacks, VkPipeline basePipelineHandle)
281 const DeviceInterface& vk = m_context.getDeviceInterface();
282 const VkDevice vkDevice = m_context.getDevice();
285 const VkVertexInputBindingDescription vertexInputBindingDescription =
287 0u, // deUint32 binding;
288 sizeof(Vertex4RGBA), // deUint32 strideInBytes;
289 VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate;
292 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] =
295 0u, // deUint32 location;
296 0u, // deUint32 binding;
297 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
298 0u // deUint32 offsetInBytes;
301 1u, // deUint32 location;
302 0u, // deUint32 binding;
303 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
304 DE_OFFSET_OF(Vertex4RGBA, color), // deUint32 offsetInBytes;
308 const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
310 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
311 DE_NULL, // const void* pNext;
312 0u, // VkPipelineVertexInputStateCreateFlags flags;
313 1u, // deUint32 vertexBindingDescriptionCount;
314 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
315 2u, // deUint32 vertexAttributeDescriptionCount;
316 vertexInputAttributeDescriptions, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
319 const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateParams =
321 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
322 DE_NULL, // const void* pNext;
323 0u, // VkPipelineInputAssemblyStateCreateFlags flags;
324 (m_patchControlPoints == 0 ? VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST
325 : VK_PRIMITIVE_TOPOLOGY_PATCH_LIST), // VkPrimitiveTopology topology;
326 VK_FALSE, // VkBool32 primitiveRestartEnable;
329 const VkViewport viewport = makeViewport(renderSize);
330 const VkRect2D scissor = makeRect2D(renderSize);
332 const VkPipelineViewportStateCreateInfo viewportStateParams =
334 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
335 DE_NULL, // const void* pNext;
336 0u, // VkPipelineViewportStateCreateFlags flags;
337 1u, // deUint32 viewportCount;
338 &viewport, // const VkViewport* pViewports;
339 1u, // deUint32 scissorCount;
340 &scissor // const VkRect2D* pScissors;
343 const VkPipelineRasterizationStateCreateInfo rasterStateParams =
345 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
346 DE_NULL, // const void* pNext;
347 0u, // 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_COUNTER_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;
360 const VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
362 VK_FALSE, // VkBool32 blendEnable;
363 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor;
364 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor;
365 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp;
366 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor;
367 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor;
368 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp;
369 VK_COLOR_COMPONENT_R_BIT |
370 VK_COLOR_COMPONENT_G_BIT |
371 VK_COLOR_COMPONENT_B_BIT |
372 VK_COLOR_COMPONENT_A_BIT // VkColorComponentFlags colorWriteMask;
375 const VkPipelineColorBlendStateCreateInfo colorBlendStateParams =
377 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
378 DE_NULL, // const void* pNext;
379 0u, // VkPipelineColorBlendStateCreateFlags flags;
380 VK_FALSE, // VkBool32 logicOpEnable;
381 VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
382 1u, // deUint32 attachmentCount;
383 &colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments;
384 { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConst[4];
387 const VkPipelineMultisampleStateCreateInfo multisampleStateParams =
389 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
390 DE_NULL, // const void* pNext;
391 0u, // VkPipelineMultisampleStateCreateFlags flags;
392 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
393 VK_FALSE, // VkBool32 sampleShadingEnable;
394 0.0f, // float minSampleShading;
395 DE_NULL, // const VkSampleMask* pSampleMask;
396 VK_FALSE, // VkBool32 alphaToCoverageEnable;
397 VK_FALSE, // VkBool32 alphaToOneEnable;
400 VkPipelineDepthStencilStateCreateInfo depthStencilStateParams =
402 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
403 DE_NULL, // const void* pNext;
404 0u, // VkPipelineDepthStencilStateCreateFlags flags;
405 VK_TRUE, // VkBool32 depthTestEnable;
406 VK_TRUE, // VkBool32 depthWriteEnable;
407 VK_COMPARE_OP_LESS_OR_EQUAL, // VkCompareOp depthCompareOp;
408 VK_FALSE, // VkBool32 depthBoundsTestEnable;
409 VK_FALSE, // VkBool32 stencilTestEnable;
410 // VkStencilOpState front;
412 VK_STENCIL_OP_KEEP, // VkStencilOp failOp;
413 VK_STENCIL_OP_KEEP, // VkStencilOp passOp;
414 VK_STENCIL_OP_KEEP, // VkStencilOp depthFailOp;
415 VK_COMPARE_OP_NEVER, // VkCompareOp compareOp;
416 0u, // deUint32 compareMask;
417 0u, // deUint32 writeMask;
418 0u, // deUint32 reference;
420 // VkStencilOpState back;
422 VK_STENCIL_OP_KEEP, // VkStencilOp failOp;
423 VK_STENCIL_OP_KEEP, // VkStencilOp passOp;
424 VK_STENCIL_OP_KEEP, // VkStencilOp depthFailOp;
425 VK_COMPARE_OP_NEVER, // VkCompareOp compareOp;
426 0u, // deUint32 compareMask;
427 0u, // deUint32 writeMask;
428 0u, // deUint32 reference;
430 0.0f, // float minDepthBounds;
431 1.0f, // float maxDepthBounds;
434 const VkPipelineTessellationStateCreateInfo tessStateCreateInfo =
436 VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, // VkStructureType sType;
437 DE_NULL, // const void* pNext;
438 0u, // VkPipelineTesselationStateCreateFlags flags;
439 m_patchControlPoints, // deUint32 patchControlPoints;
441 const VkPipelineTessellationStateCreateInfo* pTessCreateInfo = (m_patchControlPoints > 0)
442 ? &tessStateCreateInfo
445 const VkPipelineCreationFeedbackCreateInfoEXT pipelineCreationFeedbackCreateInfo =
447 VK_STRUCTURE_TYPE_PIPELINE_CREATION_FEEDBACK_CREATE_INFO_EXT, // VkStructureType sType;
448 DE_NULL, // const void* pNext;
449 pipelineCreationFeedback, // VkPipelineCreationFeedbackEXT* pPipelineCreationFeedback;
450 m_shaderStageCount, // deUint32 pipelineStageCreationFeedbackCount;
451 pipelineStageCreationFeedbacks // VkPipelineCreationFeedbackEXT* pPipelineStageCreationFeedbacks;
454 deUint32 flagsCreateInfo = VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT;
455 if (basePipelineHandle != DE_NULL)
457 flagsCreateInfo = VK_PIPELINE_CREATE_DERIVATIVE_BIT;
460 const VkGraphicsPipelineCreateInfo graphicsPipelineParams =
462 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
463 &pipelineCreationFeedbackCreateInfo, // const void* pNext;
464 flagsCreateInfo, // VkPipelineCreateFlags flags;
465 m_shaderStageCount, // deUint32 stageCount;
466 m_shaderStageInfo, // const VkPipelineShaderStageCreateInfo* pStages;
467 &vertexInputStateParams, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
468 &inputAssemblyStateParams, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
469 pTessCreateInfo, // const VkPipelineTessellationStateCreateInfo* pTessellationState;
470 &viewportStateParams, // const VkPipelineViewportStateCreateInfo* pViewportState;
471 &rasterStateParams, // const VkPipelineRasterizationStateCreateInfo* pRasterState;
472 &multisampleStateParams, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
473 &depthStencilStateParams, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
474 &colorBlendStateParams, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
475 (const VkPipelineDynamicStateCreateInfo*)DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState;
476 pipelineLayout, // VkPipelineLayout layout;
477 renderPass, // VkRenderPass renderPass;
478 0u, // deUint32 subpass;
479 basePipelineHandle, // VkPipeline basePipelineHandle;
480 basePipelineHandle != DE_NULL ? -1 : 0, // deInt32 basePipelineIndex;
483 vk.createGraphicsPipelines(vkDevice, cache, 1u, &graphicsPipelineParams, DE_NULL, &pipeline);
487 void SimpleGraphicsPipelineBuilder::enableTessellationStage (deUint32 patchControlPoints)
489 m_patchControlPoints = patchControlPoints;
492 template <class Test>
493 vkt::TestCase* newTestCase (tcu::TestContext& testContext,
494 const CacheTestParam* testParam)
496 return new Test(testContext,
497 testParam->generateTestName().c_str(),
498 testParam->generateTestDescription().c_str(),
503 class CacheTest : public vkt::TestCase
506 CacheTest(tcu::TestContext& testContext,
507 const std::string& name,
508 const std::string& description,
509 const CacheTestParam* param)
510 : vkt::TestCase (testContext, name, description)
513 virtual ~CacheTest (void) { }
515 const CacheTestParam m_param;
518 class CacheTestInstance : public vkt::TestInstance
521 CacheTestInstance (Context& context,
522 const CacheTestParam* param);
523 virtual ~CacheTestInstance (void);
524 virtual tcu::TestStatus iterate (void);
526 virtual tcu::TestStatus verifyTestResult (void) = 0;
528 const CacheTestParam* m_param;
530 Move<VkPipelineCache> m_cache;
534 CacheTestInstance::CacheTestInstance (Context& context,
535 const CacheTestParam* param)
536 : TestInstance (context)
538 , m_extensions (m_context.requireDeviceFunctionality("VK_EXT_pipeline_creation_feedback"))
540 const DeviceInterface& vk = m_context.getDeviceInterface();
541 const VkDevice vkDevice = m_context.getDevice();
543 if (m_param->isCacheDisabled() == DE_FALSE)
545 const VkPipelineCacheCreateInfo pipelineCacheCreateInfo =
547 VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO, // VkStructureType sType;
548 DE_NULL, // const void* pNext;
549 0u, // VkPipelineCacheCreateFlags flags;
550 0u, // deUintptr initialDataSize;
551 DE_NULL, // const void* pInitialData;
554 m_cache = createPipelineCache(vk, vkDevice, &pipelineCacheCreateInfo);
558 CacheTestInstance::~CacheTestInstance (void)
562 tcu::TestStatus CacheTestInstance::iterate (void)
564 return verifyTestResult();
567 class GraphicsCacheTest : public CacheTest
570 GraphicsCacheTest (tcu::TestContext& testContext,
571 const std::string& name,
572 const std::string& description,
573 const CacheTestParam* param)
574 : CacheTest (testContext, name, description, param)
576 virtual ~GraphicsCacheTest (void) { }
577 virtual void initPrograms (SourceCollections& programCollection) const;
578 virtual void checkSupport (Context& context) const;
579 virtual TestInstance* createInstance (Context& context) const;
582 class GraphicsCacheTestInstance : public CacheTestInstance
585 GraphicsCacheTestInstance (Context& context,
586 const CacheTestParam* param);
587 virtual ~GraphicsCacheTestInstance (void);
589 virtual tcu::TestStatus verifyTestResult (void);
592 const tcu::UVec2 m_renderSize;
593 const VkFormat m_colorFormat;
594 const VkFormat m_depthFormat;
595 Move<VkPipelineLayout> m_pipelineLayout;
597 SimpleGraphicsPipelineBuilder m_pipelineBuilder;
598 SimpleGraphicsPipelineBuilder m_missPipelineBuilder;
599 Move<VkRenderPass> m_renderPass;
601 VkPipeline m_pipeline[PIPELINE_CACHE_NDX_COUNT];
602 VkPipelineCreationFeedbackEXT m_pipelineCreationFeedback[PIPELINE_CACHE_NDX_COUNT];
603 VkPipelineCreationFeedbackEXT m_pipelineStageCreationFeedbacks[PIPELINE_CACHE_NDX_COUNT * VK_MAX_SHADER_STAGES];
606 void GraphicsCacheTest::initPrograms (SourceCollections& programCollection) const
608 for (deUint32 shaderNdx = 0; shaderNdx < m_param.getShaderCount(); shaderNdx++)
610 switch(m_param.getShaderFlag(shaderNdx))
612 case VK_SHADER_STAGE_VERTEX_BIT:
613 programCollection.glslSources.add("color_vert_1") << glu::VertexSource(
615 "layout(location = 0) in vec4 position;\n"
616 "layout(location = 1) in vec4 color;\n"
617 "layout(location = 0) out highp vec4 vtxColor;\n"
620 " gl_Position = position;\n"
621 " vtxColor = color;\n"
623 programCollection.glslSources.add("color_vert_2") << glu::VertexSource(
625 "layout(location = 0) in vec4 position;\n"
626 "layout(location = 1) in vec4 color;\n"
627 "layout(location = 0) out highp vec4 vtxColor;\n"
630 " gl_Position = position;\n"
631 " gl_PointSize = 1.0f;\n"
632 " vtxColor = color + vec4(0.1, 0.2, 0.3, 0.0);\n"
635 case VK_SHADER_STAGE_FRAGMENT_BIT:
636 programCollection.glslSources.add("color_frag") << glu::FragmentSource(
638 "layout(location = 0) in highp vec4 vtxColor;\n"
639 "layout(location = 0) out highp vec4 fragColor;\n"
642 " fragColor = vtxColor;\n"
646 case VK_SHADER_STAGE_GEOMETRY_BIT:
647 programCollection.glslSources.add("unused_geo") << glu::GeometrySource(
649 "layout(triangles) in;\n"
650 "layout(triangle_strip, max_vertices = 3) out;\n"
651 "layout(location = 0) in highp vec4 in_vtxColor[];\n"
652 "layout(location = 0) out highp vec4 vtxColor;\n"
653 "out gl_PerVertex { vec4 gl_Position; float gl_PointSize; };\n"
654 "in gl_PerVertex { vec4 gl_Position; float gl_PointSize; } gl_in[];\n"
657 " for(int ndx=0; ndx<3; ndx++)\n"
659 " gl_Position = gl_in[ndx].gl_Position;\n"
660 " gl_PointSize = gl_in[ndx].gl_PointSize;\n"
661 " vtxColor = in_vtxColor[ndx];\n"
668 case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
669 programCollection.glslSources.add("basic_tcs") << glu::TessellationControlSource(
671 "layout(vertices = 3) out;\n"
672 "layout(location = 0) in highp vec4 color[];\n"
673 "layout(location = 0) out highp vec4 vtxColor[];\n"
674 "out gl_PerVertex { vec4 gl_Position; float gl_PointSize; } gl_out[3];\n"
675 "in gl_PerVertex { vec4 gl_Position; float gl_PointSize; } gl_in[gl_MaxPatchVertices];\n"
678 " gl_TessLevelOuter[0] = 4.0;\n"
679 " gl_TessLevelOuter[1] = 4.0;\n"
680 " gl_TessLevelOuter[2] = 4.0;\n"
681 " gl_TessLevelInner[0] = 4.0;\n"
682 " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
683 " gl_out[gl_InvocationID].gl_PointSize = gl_in[gl_InvocationID].gl_PointSize;\n"
684 " vtxColor[gl_InvocationID] = color[gl_InvocationID];\n"
688 case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
689 programCollection.glslSources.add("basic_tes") << glu::TessellationEvaluationSource(
691 "layout(triangles, fractional_even_spacing, ccw) in;\n"
692 "layout(location = 0) in highp vec4 colors[];\n"
693 "layout(location = 0) out highp vec4 vtxColor;\n"
694 "out gl_PerVertex { vec4 gl_Position; float gl_PointSize; };\n"
695 "in gl_PerVertex { vec4 gl_Position; float gl_PointSize; } gl_in[gl_MaxPatchVertices];\n"
698 " float u = gl_TessCoord.x;\n"
699 " float v = gl_TessCoord.y;\n"
700 " float w = gl_TessCoord.z;\n"
701 " vec4 pos = vec4(0);\n"
702 " vec4 color = vec4(0);\n"
703 " pos.xyz += u * gl_in[0].gl_Position.xyz;\n"
704 " color.xyz += u * colors[0].xyz;\n"
705 " pos.xyz += v * gl_in[1].gl_Position.xyz;\n"
706 " color.xyz += v * colors[1].xyz;\n"
707 " pos.xyz += w * gl_in[2].gl_Position.xyz;\n"
708 " color.xyz += w * colors[2].xyz;\n"
711 " gl_Position = pos;\n"
712 " gl_PointSize = gl_in[0].gl_PointSize;"
713 " vtxColor = color;\n"
718 DE_FATAL("Unknown Shader Stage!");
724 void GraphicsCacheTest::checkSupport (Context& context) const
726 for (deUint32 shaderNdx = 0; shaderNdx < m_param.getShaderCount(); shaderNdx++)
728 switch(m_param.getShaderFlag(shaderNdx))
730 case VK_SHADER_STAGE_GEOMETRY_BIT:
731 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
733 case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
734 case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
735 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_TESSELLATION_SHADER);
743 TestInstance* GraphicsCacheTest::createInstance (Context& context) const
745 return new GraphicsCacheTestInstance(context, &m_param);
748 GraphicsCacheTestInstance::GraphicsCacheTestInstance (Context& context,
749 const CacheTestParam* param)
750 : CacheTestInstance (context, param)
751 , m_renderSize (32u, 32u)
752 , m_colorFormat (VK_FORMAT_R8G8B8A8_UNORM)
753 , m_depthFormat (VK_FORMAT_D16_UNORM)
754 , m_pipelineBuilder (context)
755 , m_missPipelineBuilder (context)
757 const DeviceInterface& vk = m_context.getDeviceInterface();
758 const VkDevice vkDevice = m_context.getDevice();
760 // Create pipeline layout
762 const VkPipelineLayoutCreateInfo pipelineLayoutParams =
764 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
765 DE_NULL, // const void* pNext;
766 0u, // VkPipelineLayoutCreateFlags flags;
767 0u, // deUint32 setLayoutCount;
768 DE_NULL, // const VkDescriptorSetLayout* pSetLayouts;
769 0u, // deUint32 pushConstantRangeCount;
770 DE_NULL // const VkPushConstantRange* pPushConstantRanges;
773 m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
776 // Create render pass
777 m_renderPass = makeRenderPass(vk, vkDevice, m_colorFormat, m_depthFormat);
779 // Bind shader stages
780 for (deUint32 ndx = 0; ndx < PIPELINE_CACHE_NDX_COUNT; ndx++)
782 for (deUint32 shaderNdx = 0; shaderNdx < m_param->getShaderCount(); shaderNdx++)
784 switch(m_param->getShaderFlag(shaderNdx))
786 case VK_SHADER_STAGE_VERTEX_BIT:
788 std::string shader_name("color_vert_");
789 shader_name += (ndx == PIPELINE_CACHE_NDX_DERIVATIVE) ? "2" : "1";
790 m_pipelineBuilder.bindShaderStage(VK_SHADER_STAGE_VERTEX_BIT, shader_name.c_str(), "main");
793 case VK_SHADER_STAGE_FRAGMENT_BIT:
794 m_pipelineBuilder.bindShaderStage(VK_SHADER_STAGE_FRAGMENT_BIT, "color_frag", "main");
796 case VK_SHADER_STAGE_GEOMETRY_BIT:
797 m_pipelineBuilder.bindShaderStage(VK_SHADER_STAGE_GEOMETRY_BIT, "unused_geo", "main");
799 case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
800 m_pipelineBuilder.bindShaderStage(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, "basic_tcs", "main");
801 m_pipelineBuilder.enableTessellationStage(3);
803 case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
804 m_pipelineBuilder.bindShaderStage(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, "basic_tes", "main");
805 m_pipelineBuilder.enableTessellationStage(3);
808 DE_FATAL("Unknown Shader Stage!");
812 if (ndx == PIPELINE_CACHE_NDX_CACHED && !param->isDelayedDestroy())
814 // Destroy the NO_CACHE pipeline to check that the cached one really hits cache,
815 // except for the case where we're testing cache hit of a pipeline still active.
816 vk.destroyPipeline(vkDevice, m_pipeline[PIPELINE_CACHE_NDX_NO_CACHE], DE_NULL);
819 m_pipeline[ndx] = m_pipelineBuilder.buildPipeline(m_renderSize, *m_renderPass, *m_cache, *m_pipelineLayout,
820 &m_pipelineCreationFeedback[ndx],
821 &m_pipelineStageCreationFeedbacks[VK_MAX_SHADER_STAGES * ndx],
822 ndx == PIPELINE_CACHE_NDX_DERIVATIVE ? m_pipeline[PIPELINE_CACHE_NDX_NO_CACHE] : DE_NULL);
823 m_pipelineBuilder.resetBuilder();
825 if (ndx != PIPELINE_CACHE_NDX_NO_CACHE)
827 // Destroy the pipeline as soon as it is created, except the NO_CACHE because
828 // it is needed as a base pipeline for the derivative case.
829 vk.destroyPipeline(vkDevice, m_pipeline[ndx], DE_NULL);
831 if (ndx == PIPELINE_CACHE_NDX_CACHED && param->isDelayedDestroy())
833 // Destroy the pipeline we didn't destroy earlier for the isDelayedDestroy case.
834 vk.destroyPipeline(vkDevice, m_pipeline[PIPELINE_CACHE_NDX_NO_CACHE], DE_NULL);
840 GraphicsCacheTestInstance::~GraphicsCacheTestInstance (void)
844 tcu::TestStatus GraphicsCacheTestInstance::verifyTestResult (void)
846 tcu::TestLog &log = m_context.getTestContext().getLog();
847 bool durationZeroWarning = DE_FALSE;
848 bool cachedPipelineWarning = DE_FALSE;
850 for (deUint32 ndx = 0; ndx < PIPELINE_CACHE_NDX_COUNT; ndx++)
852 std::ostringstream message;
853 message << getCaseStr(ndx);
855 // No need to check per stage status as it is compute pipeline (only one stage) and Vulkan spec mentions that:
856 // "One common scenario for an implementation to skip per-stage feedback is when
857 // VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT is set in pPipelineCreationFeedback."
859 // Check first that the no cached pipeline was missed in the pipeline cache
860 if (!(m_pipelineCreationFeedback[ndx].flags & VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT_EXT))
862 message << ": invalid data";
863 return tcu::TestStatus::fail(message.str());
866 if (m_param->isCacheDisabled() && m_pipelineCreationFeedback[ndx].flags & VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT)
868 message << ": feedback indicates pipeline hit cache when it shouldn't";
869 return tcu::TestStatus::fail(message.str());
872 if (ndx == PIPELINE_CACHE_NDX_NO_CACHE && m_pipelineCreationFeedback[ndx].flags & VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT)
874 message << ": hit the cache when it shouldn't";
875 return tcu::TestStatus::fail(message.str());
878 if (ndx != PIPELINE_CACHE_NDX_DERIVATIVE && m_pipelineCreationFeedback[ndx].flags & VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT_EXT)
880 message << ": feedback indicates base pipeline acceleration when it shouldn't";
881 return tcu::TestStatus::fail(message.str());
884 if (ndx == PIPELINE_CACHE_NDX_CACHED && !m_param->isCacheDisabled() && (m_pipelineCreationFeedback[ndx].flags & VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT) == 0)
886 message << "\nWarning: Cached pipeline case did not hit the cache";
887 cachedPipelineWarning = DE_TRUE;
890 if (m_pipelineCreationFeedback[ndx].duration == 0)
892 message << "\nWarning: Pipeline creation feedback reports duration spent creating a pipeline was zero nanoseconds\n";
893 durationZeroWarning = DE_TRUE;
897 message << "\t\t Hit cache ? \t\t\t" << (m_pipelineCreationFeedback[ndx].flags & VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT ? "yes" : "no") << "\n";
898 message << "\t\t Base Pipeline Acceleration ? \t" << (m_pipelineCreationFeedback[ndx].flags & VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT_EXT ? "yes" : "no") << "\n";
899 message << "\t\t Duration (ns): \t\t" << m_pipelineCreationFeedback[ndx].duration << "\n";
901 for(deUint32 shader = 0; shader < m_param->getShaderCount(); shader++)
903 const deUint32 index = VK_MAX_SHADER_STAGES * ndx + shader;
904 message << "\t" << getShaderFlagStr(m_param->getShaderFlag(shader), true) << "\n";
906 if (!(m_pipelineStageCreationFeedbacks[index].flags & VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT_EXT))
908 if (m_pipelineStageCreationFeedbacks[index].flags)
910 std::ostringstream errorMsg;
911 errorMsg << getCaseStr(ndx) << ": Creation feedback is not valid for " + getShaderFlagStr(m_param->getShaderFlag(shader), true) + " but there are other flags written";
912 return tcu::TestStatus::fail(errorMsg.str());
914 message << "\t\t Pipeline Creation Feedback data is not valid\n";
917 if (m_param->isCacheDisabled() && m_pipelineStageCreationFeedbacks[index].flags & VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT)
919 std::ostringstream errorMsg;
920 errorMsg << getCaseStr(ndx) << ": feedback indicates pipeline " + getShaderFlagStr(m_param->getShaderFlag(shader), true) + " stage hit cache when it shouldn't";
921 return tcu::TestStatus::fail(errorMsg.str());
924 if (ndx == PIPELINE_CACHE_NDX_CACHED && !m_param->isCacheDisabled() && (m_pipelineStageCreationFeedbacks[index].flags & VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT) == 0)
926 message << "Warning: pipeline stage did not hit the cache\n";
927 cachedPipelineWarning = DE_TRUE;
929 if (cachedPipelineWarning && m_pipelineStageCreationFeedbacks[index].flags & VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT)
931 // We only set the warning when the pipeline nor the pipeline stages hit the cache. If any of them did, them disable the warning.
932 cachedPipelineWarning = DE_FALSE;
935 message << "\t\t Hit cache ? \t\t\t" << (m_pipelineStageCreationFeedbacks[index].flags & VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT ? "yes" : "no") << "\n";
936 message << "\t\t Base Pipeline Acceleration ? \t" << (m_pipelineStageCreationFeedbacks[index].flags & VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT_EXT ? "yes" : "no") << "\n";
937 message << "\t\t Duration (ns): \t\t" << m_pipelineStageCreationFeedbacks[index].duration << "\n";
940 log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage;
943 if (cachedPipelineWarning)
945 return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Cached pipeline or stage did not hit the cache");
947 if (durationZeroWarning)
949 return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Pipeline creation feedback reports duration spent creating a pipeline was zero nanoseconds");
951 return tcu::TestStatus::pass("Pass");
954 class ComputeCacheTest : public CacheTest
957 ComputeCacheTest (tcu::TestContext& testContext,
958 const std::string& name,
959 const std::string& description,
960 const CacheTestParam* param)
961 : CacheTest (testContext, name, description, param)
963 virtual ~ComputeCacheTest (void) { }
964 virtual void initPrograms (SourceCollections& programCollection) const;
965 virtual TestInstance* createInstance (Context& context) const;
968 class ComputeCacheTestInstance : public CacheTestInstance
971 ComputeCacheTestInstance (Context& context,
972 const CacheTestParam* param);
973 virtual ~ComputeCacheTestInstance (void);
975 virtual tcu::TestStatus verifyTestResult (void);
976 void buildDescriptorSets (deUint32 ndx);
977 void buildShader (deUint32 ndx);
978 void buildPipeline (const CacheTestParam* param, deUint32 ndx);
980 Move<VkBuffer> m_inputBuf;
981 de::MovePtr<Allocation> m_inputBufferAlloc;
982 Move<VkShaderModule> m_computeShaderModule[PIPELINE_CACHE_NDX_COUNT];
984 Move<VkBuffer> m_outputBuf[PIPELINE_CACHE_NDX_COUNT];
985 de::MovePtr<Allocation> m_outputBufferAlloc[PIPELINE_CACHE_NDX_COUNT];
987 Move<VkDescriptorPool> m_descriptorPool[PIPELINE_CACHE_NDX_COUNT];
988 Move<VkDescriptorSetLayout> m_descriptorSetLayout[PIPELINE_CACHE_NDX_COUNT];
989 Move<VkDescriptorSet> m_descriptorSet[PIPELINE_CACHE_NDX_COUNT];
991 Move<VkPipelineLayout> m_pipelineLayout[PIPELINE_CACHE_NDX_COUNT];
992 VkPipeline m_pipeline[PIPELINE_CACHE_NDX_COUNT];
993 VkPipelineCreationFeedbackEXT m_pipelineCreationFeedback[PIPELINE_CACHE_NDX_COUNT];
994 VkPipelineCreationFeedbackEXT m_pipelineStageCreationFeedback[PIPELINE_CACHE_NDX_COUNT];
997 void ComputeCacheTest::initPrograms (SourceCollections& programCollection) const
999 programCollection.glslSources.add("basic_compute_1") << glu::ComputeSource(
1001 "layout(local_size_x = 1) in;\n"
1002 "layout(std430) buffer;\n"
1003 "layout(binding = 0) readonly buffer Input0\n"
1005 " vec4 elements[];\n"
1007 "layout(binding = 1) writeonly buffer Output\n"
1009 " vec4 elements[];\n"
1013 " uint ident = gl_GlobalInvocationID.x;\n"
1014 " output_data.elements[ident] = input_data0.elements[ident] * input_data0.elements[ident];\n"
1016 programCollection.glslSources.add("basic_compute_2") << glu::ComputeSource(
1018 "layout(local_size_x = 1) in;\n"
1019 "layout(std430) buffer;\n"
1020 "layout(binding = 0) readonly buffer Input0\n"
1022 " vec4 elements[];\n"
1024 "layout(binding = 1) writeonly buffer Output\n"
1026 " vec4 elements[];\n"
1030 " uint ident = gl_GlobalInvocationID.x;\n"
1031 " output_data.elements[ident] = input_data0.elements[ident];\n"
1035 TestInstance* ComputeCacheTest::createInstance (Context& context) const
1037 return new ComputeCacheTestInstance(context, &m_param);
1040 void ComputeCacheTestInstance::buildDescriptorSets (deUint32 ndx)
1042 const DeviceInterface& vk = m_context.getDeviceInterface();
1043 const VkDevice vkDevice = m_context.getDevice();
1045 // Create descriptor set layout
1046 DescriptorSetLayoutBuilder descLayoutBuilder;
1047 for (deUint32 bindingNdx = 0u; bindingNdx < 2u; bindingNdx++)
1048 descLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT);
1049 m_descriptorSetLayout[ndx] = descLayoutBuilder.build(vk, vkDevice);
1052 void ComputeCacheTestInstance::buildShader (deUint32 ndx)
1054 const DeviceInterface& vk = m_context.getDeviceInterface();
1055 const VkDevice vkDevice = m_context.getDevice();
1057 std::string shader_name("basic_compute_");
1059 shader_name += (ndx == PIPELINE_CACHE_NDX_DERIVATIVE) ? "2" : "1";
1061 // Create compute shader
1062 VkShaderModuleCreateInfo shaderModuleCreateInfo =
1064 VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, // VkStructureType sType;
1065 DE_NULL, // const void* pNext;
1066 0u, // VkShaderModuleCreateFlags flags;
1067 m_context.getBinaryCollection().get(shader_name).getSize(), // deUintptr codeSize;
1068 (deUint32*)m_context.getBinaryCollection().get(shader_name).getBinary(), // const deUint32* pCode;
1070 m_computeShaderModule[ndx] = createShaderModule(vk, vkDevice, &shaderModuleCreateInfo);
1073 void ComputeCacheTestInstance::buildPipeline (const CacheTestParam* param, deUint32 ndx)
1075 const DeviceInterface& vk = m_context.getDeviceInterface();
1076 const VkDevice vkDevice = m_context.getDevice();
1078 deMemset(&m_pipelineCreationFeedback[ndx], 0, sizeof(VkPipelineCreationFeedbackEXT));
1079 deMemset(&m_pipelineStageCreationFeedback[ndx], 0, sizeof(VkPipelineCreationFeedbackEXT));
1081 const VkPipelineCreationFeedbackCreateInfoEXT pipelineCreationFeedbackCreateInfo =
1083 VK_STRUCTURE_TYPE_PIPELINE_CREATION_FEEDBACK_CREATE_INFO_EXT, // VkStructureType sType;
1084 DE_NULL, // const void * pNext;
1085 &m_pipelineCreationFeedback[ndx], // VkPipelineCreationFeedbackEXT* pPipelineCreationFeedback;
1086 1u, // deUint32 pipelineStageCreationFeedbackCount;
1087 &m_pipelineStageCreationFeedback[ndx] // VkPipelineCreationFeedbackEXT* pPipelineStageCreationFeedbacks;
1090 // Create compute pipeline layout
1091 const VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo =
1093 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
1094 DE_NULL, // const void* pNext;
1095 0u, // VkPipelineLayoutCreateFlags flags;
1096 1u, // deUint32 setLayoutCount;
1097 &m_descriptorSetLayout[ndx].get(), // const VkDescriptorSetLayout* pSetLayouts;
1098 0u, // deUint32 pushConstantRangeCount;
1099 DE_NULL, // const VkPushConstantRange* pPushConstantRanges;
1102 m_pipelineLayout[ndx] = createPipelineLayout(vk, vkDevice, &pipelineLayoutCreateInfo);
1104 const VkPipelineShaderStageCreateInfo stageCreateInfo =
1106 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
1107 DE_NULL, // const void* pNext;
1108 0u, // VkPipelineShaderStageCreateFlags flags;
1109 VK_SHADER_STAGE_COMPUTE_BIT, // VkShaderStageFlagBits stage;
1110 *m_computeShaderModule[ndx], // VkShaderModule module;
1111 "main", // const char* pName;
1112 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
1115 VkComputePipelineCreateInfo pipelineCreateInfo =
1117 VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, // VkStructureType sType;
1118 &pipelineCreationFeedbackCreateInfo, // const void* pNext;
1119 0u, // VkPipelineCreateFlags flags;
1120 stageCreateInfo, // VkPipelineShaderStageCreateInfo stage;
1121 *m_pipelineLayout[ndx], // VkPipelineLayout layout;
1122 (VkPipeline)0, // VkPipeline basePipelineHandle;
1123 0u, // deInt32 basePipelineIndex;
1126 if (ndx != PIPELINE_CACHE_NDX_DERIVATIVE)
1128 pipelineCreateInfo.flags = VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT;
1131 if (ndx == PIPELINE_CACHE_NDX_DERIVATIVE)
1133 pipelineCreateInfo.flags = VK_PIPELINE_CREATE_DERIVATIVE_BIT;
1134 pipelineCreateInfo.basePipelineHandle = m_pipeline[PIPELINE_CACHE_NDX_NO_CACHE];
1135 pipelineCreateInfo.basePipelineIndex = -1;
1138 if (ndx == PIPELINE_CACHE_NDX_CACHED && !param->isDelayedDestroy())
1140 // Destroy the NO_CACHE pipeline to check that the cached one really hits cache,
1141 // except for the case where we're testing cache hit of a pipeline still active.
1142 vk.destroyPipeline(vkDevice, m_pipeline[PIPELINE_CACHE_NDX_NO_CACHE], DE_NULL);
1145 vk.createComputePipelines(vkDevice, *m_cache, 1u, &pipelineCreateInfo, DE_NULL, &m_pipeline[ndx]);
1147 if (ndx != PIPELINE_CACHE_NDX_NO_CACHE)
1149 // Destroy the pipeline as soon as it is created, except the NO_CACHE because
1150 // it is needed as a base pipeline for the derivative case.
1151 vk.destroyPipeline(vkDevice, m_pipeline[ndx], DE_NULL);
1153 if (ndx == PIPELINE_CACHE_NDX_CACHED && param->isDelayedDestroy())
1155 // Destroy the pipeline we didn't destroy earlier for the isDelayedDestroy case.
1156 vk.destroyPipeline(vkDevice, m_pipeline[PIPELINE_CACHE_NDX_NO_CACHE], DE_NULL);
1161 ComputeCacheTestInstance::ComputeCacheTestInstance (Context& context,
1162 const CacheTestParam* param)
1163 : CacheTestInstance (context, param)
1165 for (deUint32 ndx = 0; ndx < PIPELINE_CACHE_NDX_COUNT; ndx++)
1167 buildDescriptorSets(ndx);
1169 buildPipeline(param, ndx);
1173 ComputeCacheTestInstance::~ComputeCacheTestInstance (void)
1177 tcu::TestStatus ComputeCacheTestInstance::verifyTestResult (void)
1179 tcu::TestLog &log = m_context.getTestContext().getLog();
1180 deBool durationZeroWarning = DE_FALSE;
1181 deBool cachedPipelineWarning = DE_FALSE;
1183 for (deUint32 ndx = 0; ndx < PIPELINE_CACHE_NDX_COUNT; ndx++)
1185 std::ostringstream message;
1186 message << getCaseStr(ndx);
1188 // No need to check per stage status as it is compute pipeline (only one stage) and Vulkan spec mentions that:
1189 // "One common scenario for an implementation to skip per-stage feedback is when
1190 // VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT is set in pPipelineCreationFeedback."
1192 // Check first that the no cached pipeline was missed in the pipeline cache
1193 if (!(m_pipelineCreationFeedback[ndx].flags & VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT_EXT))
1195 message << ": invalid data";
1196 return tcu::TestStatus::fail(message.str());
1199 if (m_param->isCacheDisabled() && m_pipelineCreationFeedback[ndx].flags & VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT)
1201 message << ": feedback indicates pipeline hit cache when it shouldn't";
1202 return tcu::TestStatus::fail(message.str());
1205 if (ndx == PIPELINE_CACHE_NDX_NO_CACHE && m_pipelineCreationFeedback[ndx].flags & VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT)
1207 message << ": hit the cache when it shouldn't";
1208 return tcu::TestStatus::fail(message.str());
1211 if (!(ndx == PIPELINE_CACHE_NDX_DERIVATIVE && !m_param->isCacheDisabled()) && m_pipelineCreationFeedback[ndx].flags & VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT_EXT)
1213 message << ": feedback indicates base pipeline acceleration when it shouldn't";
1214 return tcu::TestStatus::fail(message.str());
1217 if (ndx == PIPELINE_CACHE_NDX_CACHED && !m_param->isCacheDisabled() && (m_pipelineCreationFeedback[ndx].flags & VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT) == 0)
1219 message << "\nWarning: Cached pipeline case did not hit the cache";
1220 cachedPipelineWarning = DE_TRUE;
1223 if (m_pipelineCreationFeedback[ndx].duration == 0)
1225 message << "\nWarning: Pipeline creation feedback reports duration spent creating a pipeline was zero nanoseconds\n";
1226 durationZeroWarning = DE_TRUE;
1231 message << "\t\t Hit cache ? \t\t\t" << (m_pipelineCreationFeedback[ndx].flags & VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT ? "yes" : "no") << "\n";
1232 message << "\t\t Base Pipeline Acceleration ? \t" << (m_pipelineCreationFeedback[ndx].flags & VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT_EXT ? "yes" : "no") << "\n";
1233 message << "\t\t Duration (ns): \t\t" << m_pipelineCreationFeedback[ndx].duration << "\n";
1235 message << "\t Compute Stage\n";
1237 // According to the spec:
1239 // "An implementation should write pipeline creation feedback to pPipelineCreationFeedback and
1240 // may write pipeline stage creation feedback to pPipelineStageCreationFeedbacks."
1241 if (!(m_pipelineStageCreationFeedback[ndx].flags & VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT_EXT))
1243 // According to the spec:
1244 // "If the VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT_EXT is not set in flags, an implementation
1245 // must not set any other bits in flags, and all other VkPipelineCreationFeedbackEXT data members are undefined."
1246 if (m_pipelineStageCreationFeedback[ndx].flags)
1248 std::ostringstream errorMsg;
1249 errorMsg << getCaseStr(ndx) << ": Creation feedback is not valid for compute stage but there are other flags written";
1250 return tcu::TestStatus::fail(errorMsg.str());
1252 message << "\t\t Pipeline Creation Feedback data is not valid\n";
1256 if (m_param->isCacheDisabled() && m_pipelineStageCreationFeedback[ndx].flags & VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT)
1258 std::ostringstream errorMsg;
1259 errorMsg << getCaseStr(ndx) << ": feedback indicates pipeline compute stage hit cache when it shouldn't";
1260 return tcu::TestStatus::fail(errorMsg.str());
1263 if (ndx == PIPELINE_CACHE_NDX_CACHED && !m_param->isCacheDisabled() && (m_pipelineStageCreationFeedback[ndx].flags & VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT) == 0)
1265 message << "Warning: pipeline stage did not hit the cache\n";
1266 cachedPipelineWarning = DE_TRUE;
1268 if (cachedPipelineWarning && m_pipelineStageCreationFeedback[ndx].flags & VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT)
1270 // We only set the warning when the pipeline nor the pipeline stages hit the cache. If any of them did, them disable the warning.
1271 cachedPipelineWarning = DE_FALSE;
1274 message << "\t\t Hit cache ? \t\t\t" << (m_pipelineStageCreationFeedback[ndx].flags & VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT ? "yes" : "no") << "\n";
1275 message << "\t\t Base Pipeline Acceleration ? \t" << (m_pipelineStageCreationFeedback[ndx].flags & VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT_EXT ? "yes" : "no") << "\n";
1276 message << "\t\t Duration (ns): \t\t" << m_pipelineStageCreationFeedback[ndx].duration << "\n";
1279 log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage;
1282 if (cachedPipelineWarning)
1284 return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Cached pipeline or stage did not hit the cache");
1286 if (durationZeroWarning)
1288 return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Pipeline creation feedback reports duration spent creating a pipeline was zero nanoseconds");
1290 return tcu::TestStatus::pass("Pass");
1294 tcu::TestCaseGroup* createCreationFeedbackTests (tcu::TestContext& testCtx)
1296 de::MovePtr<tcu::TestCaseGroup> cacheTests (new tcu::TestCaseGroup(testCtx, "creation_feedback", "pipeline creation feedback tests"));
1298 // Graphics Pipeline Tests
1300 de::MovePtr<tcu::TestCaseGroup> graphicsTests (new tcu::TestCaseGroup(testCtx, "graphics_tests", "Test pipeline creation feedback with graphics pipeline."));
1302 const VkShaderStageFlagBits testParamShaders0[] =
1304 VK_SHADER_STAGE_VERTEX_BIT,
1305 VK_SHADER_STAGE_FRAGMENT_BIT,
1307 const VkShaderStageFlagBits testParamShaders1[] =
1309 VK_SHADER_STAGE_VERTEX_BIT,
1310 VK_SHADER_STAGE_GEOMETRY_BIT,
1311 VK_SHADER_STAGE_FRAGMENT_BIT,
1313 const VkShaderStageFlagBits testParamShaders2[] =
1315 VK_SHADER_STAGE_VERTEX_BIT,
1316 VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
1317 VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
1318 VK_SHADER_STAGE_FRAGMENT_BIT,
1320 const CacheTestParam testParams[] =
1322 CacheTestParam(testParamShaders0, DE_LENGTH_OF_ARRAY(testParamShaders0), DE_FALSE, DE_FALSE),
1323 CacheTestParam(testParamShaders1, DE_LENGTH_OF_ARRAY(testParamShaders1), DE_FALSE, DE_FALSE),
1324 CacheTestParam(testParamShaders2, DE_LENGTH_OF_ARRAY(testParamShaders2), DE_FALSE, DE_FALSE),
1325 CacheTestParam(testParamShaders0, DE_LENGTH_OF_ARRAY(testParamShaders0), DE_TRUE, DE_FALSE),
1326 CacheTestParam(testParamShaders1, DE_LENGTH_OF_ARRAY(testParamShaders1), DE_TRUE, DE_FALSE),
1327 CacheTestParam(testParamShaders2, DE_LENGTH_OF_ARRAY(testParamShaders2), DE_TRUE, DE_FALSE),
1328 CacheTestParam(testParamShaders0, DE_LENGTH_OF_ARRAY(testParamShaders0), DE_FALSE, DE_TRUE),
1329 CacheTestParam(testParamShaders1, DE_LENGTH_OF_ARRAY(testParamShaders1), DE_FALSE, DE_TRUE),
1330 CacheTestParam(testParamShaders2, DE_LENGTH_OF_ARRAY(testParamShaders2), DE_FALSE, DE_TRUE),
1333 for (deUint32 i = 0; i < DE_LENGTH_OF_ARRAY(testParams); i++)
1334 graphicsTests->addChild(newTestCase<GraphicsCacheTest>(testCtx, &testParams[i]));
1336 cacheTests->addChild(graphicsTests.release());
1339 // Compute Pipeline Tests
1341 de::MovePtr<tcu::TestCaseGroup> computeTests (new tcu::TestCaseGroup(testCtx, "compute_tests", "Test pipeline creation feedback with compute pipeline."));
1343 const VkShaderStageFlagBits testParamShaders0[] =
1345 VK_SHADER_STAGE_COMPUTE_BIT,
1347 const CacheTestParam testParams[] =
1349 CacheTestParam(testParamShaders0, DE_LENGTH_OF_ARRAY(testParamShaders0), DE_FALSE, DE_FALSE),
1350 CacheTestParam(testParamShaders0, DE_LENGTH_OF_ARRAY(testParamShaders0), DE_TRUE, DE_FALSE),
1351 CacheTestParam(testParamShaders0, DE_LENGTH_OF_ARRAY(testParamShaders0), DE_FALSE, DE_TRUE),
1354 for (deUint32 i = 0; i < DE_LENGTH_OF_ARRAY(testParams); i++)
1355 computeTests->addChild(newTestCase<ComputeCacheTest>(testCtx, &testParams[i]));
1357 cacheTests->addChild(computeTests.release());
1360 return cacheTests.release();