1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2019 The Khronos Group Inc.
6 * Copyright (c) 2019 Intel Corporation.
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 VK_KHR_pipeline_executable_properties
23 *
24 * These tests creates compute and graphics pipelines with a variety of
25 * stages both with and without a pipeline cache and exercise the new
26 * queries provided by VK_KHR_pipeline_executable_properties.
27 *
28 * For each query type, it asserts that the query works and doesn't crash
29 * and returns consistent results:
30 *
31 * - The tests assert that the same set of pipeline executables is
32 * reported regardless of whether or not a pipeline cache is used.
33 *
34 * - For each pipeline executable, the tests assert that the same set of
35 * statistics is returned regardless of whether or not a pipeline cache
36 * is used.
37 *
38 * - For each pipeline executable, the tests assert that the same set of
39 * statistics is returned regardless of whether or not
40 * CAPTURE_INTERNAL_REPRESENTATIONS_BIT is set.
41 *
42 * - For each pipeline executable, the tests assert that the same set of
43 * internal representations is returned regardless of whether or not a
44 * pipeline cache is used.
45 *
46 * - For each string returned (statistic names, etc.) the tests assert
47 * that the string is NULL terminated.
48 *
49 * - For each statistic, the tests compare the results of the two
50 * compilations and report any differences. (Statistics differing
51 * between two compilations is not considered a failure.)
52 *
53 * - For each binary internal representation, the tests attempt to assert
54 * that the amount of data returned by the implementation matches the
55 * amount the implementation claims. (It's impossible to exactly do
56 * this but the tests give it a good try.)
57 *
58 * All of the returned data is recorded in the output file.
59 *
60 *//*--------------------------------------------------------------------*/
61
62 #include "vktPipelineExecutablePropertiesTests.hpp"
63 #include "vktPipelineVertexUtil.hpp"
64 #include "vktTestCase.hpp"
65 #include "vktTestCaseUtil.hpp"
66 #include "vkMemUtil.hpp"
67 #include "vkBuilderUtil.hpp"
68 #include "vkRefUtil.hpp"
69 #include "vkTypeUtil.hpp"
70 #include "vkObjUtil.hpp"
71 #include "tcuTestLog.hpp"
72
73 #include <sstream>
74 #include <vector>
75
76 namespace vkt
77 {
78 namespace pipeline
79 {
80
81 using namespace vk;
82
83 namespace
84 {
85 enum
86 {
87 VK_MAX_SHADER_STAGES = 6,
88 };
89
90 enum
91 {
92 PIPELINE_CACHE_NDX_INITIAL = 0,
93 PIPELINE_CACHE_NDX_CACHED = 1,
94 PIPELINE_CACHE_NDX_COUNT,
95 };
96
97 // helper functions
98
getShaderFlagStr(const VkShaderStageFlagBits shader,bool isDescription)99 std::string getShaderFlagStr (const VkShaderStageFlagBits shader,
100 bool isDescription)
101 {
102 std::ostringstream desc;
103 switch(shader)
104 {
105 case VK_SHADER_STAGE_VERTEX_BIT:
106 {
107 desc << ((isDescription) ? "vertex" : "vertex_stage");
108 break;
109 }
110 case VK_SHADER_STAGE_FRAGMENT_BIT:
111 {
112 desc << ((isDescription) ? "fragment" : "fragment_stage");
113 break;
114 }
115 case VK_SHADER_STAGE_GEOMETRY_BIT:
116 {
117 desc << ((isDescription) ? "geometry" : "geometry_stage");
118 break;
119 }
120 case VK_SHADER_STAGE_COMPUTE_BIT:
121 {
122 desc << ((isDescription) ? "compute" : "compute_stage");
123 break;
124 }
125 case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
126 {
127 desc << ((isDescription) ? "tessellation control" : "tessellation_control_stage");
128 break;
129 }
130 case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
131 {
132 desc << ((isDescription) ? "tessellation evaluation" : "tessellation_evaluation_stage");
133 break;
134 }
135 default:
136 desc << "unknown shader stage!";
137 DE_FATAL("Unknown shader Stage!");
138 break;
139 }
140
141 return desc.str();
142 }
143
getShaderFlagsStr(const VkShaderStageFlags flags)144 std::string getShaderFlagsStr (const VkShaderStageFlags flags)
145 {
146 std::ostringstream stream;
147 bool empty = true;
148 for (deUint32 b = 0; b < 8 * sizeof(flags); b++)
149 {
150 if (flags & (1u << b))
151 {
152 if (empty)
153 {
154 empty = false;
155 }
156 else
157 {
158 stream << ", ";
159 }
160
161 stream << getShaderFlagStr((VkShaderStageFlagBits)(1u << b), true);
162 }
163 }
164
165 if (empty)
166 {
167 stream << "none";
168 }
169
170 return stream.str();
171 }
172
173 // helper classes
174 class ExecutablePropertiesTestParam
175 {
176 public:
177 ExecutablePropertiesTestParam (const VkShaderStageFlagBits* shaders,
178 deUint32 count,
179 deBool testStatistics,
180 deBool testInternalRepresentations);
181 virtual ~ExecutablePropertiesTestParam (void);
182 virtual const std::string generateTestName (void) const;
183 virtual const std::string generateTestDescription (void) const;
getShaderFlag(deUint32 ndx) const184 VkShaderStageFlagBits getShaderFlag (deUint32 ndx) const { return m_shaders[ndx]; }
getShaderCount(void) const185 deUint32 getShaderCount (void) const { return (deUint32)m_shaderCount; }
getTestStatistics(void) const186 deBool getTestStatistics (void) const { return m_testStatistics; }
getTestInternalRepresentations(void) const187 deBool getTestInternalRepresentations (void) const { return m_testInternalRepresentations; }
188
189 protected:
190 VkShaderStageFlagBits m_shaders[VK_MAX_SHADER_STAGES];
191 size_t m_shaderCount;
192 bool m_testStatistics;
193 bool m_testInternalRepresentations;
194 };
195
ExecutablePropertiesTestParam(const VkShaderStageFlagBits * shaders,deUint32 count,deBool testStatistics,deBool testInternalRepresentations)196 ExecutablePropertiesTestParam::ExecutablePropertiesTestParam (const VkShaderStageFlagBits* shaders, deUint32 count, deBool testStatistics, deBool testInternalRepresentations)
197 {
198 DE_ASSERT(count <= VK_MAX_SHADER_STAGES);
199 for (deUint32 ndx = 0; ndx < count; ndx++)
200 m_shaders[ndx] = shaders[ndx];
201 m_shaderCount = count;
202 m_testStatistics = testStatistics;
203 m_testInternalRepresentations = testInternalRepresentations;
204 }
205
~ExecutablePropertiesTestParam(void)206 ExecutablePropertiesTestParam::~ExecutablePropertiesTestParam (void)
207 {
208 }
209
generateTestName(void) const210 const std::string ExecutablePropertiesTestParam::generateTestName (void) const
211 {
212 std::string result(getShaderFlagStr(m_shaders[0], false));
213
214 for(deUint32 ndx = 1; ndx < m_shaderCount; ndx++)
215 {
216 result += '_' + getShaderFlagStr(m_shaders[ndx], false);
217 }
218
219 if (m_testStatistics)
220 {
221 result += "_statistics";
222 }
223
224 if (m_testInternalRepresentations)
225 {
226 result += "_internal_representations";
227 }
228
229 return result;
230 }
231
generateTestDescription(void) const232 const std::string ExecutablePropertiesTestParam::generateTestDescription (void) const
233 {
234 std::string result;
235 if (m_testStatistics)
236 {
237 result += "Get pipeline executable statistics";
238 if (m_testInternalRepresentations)
239 {
240 result += " and internal representations";
241 }
242 }
243 else if (m_testInternalRepresentations)
244 {
245 result += "Get pipeline executable internal representations";
246 }
247 else
248 {
249 result += "Get pipeline executable properties";
250 }
251
252 result += " with " + getShaderFlagStr(m_shaders[0], true);
253
254 return result;
255 }
256
257 class SimpleGraphicsPipelineBuilder
258 {
259 public:
260 SimpleGraphicsPipelineBuilder (Context& context);
~SimpleGraphicsPipelineBuilder(void)261 ~SimpleGraphicsPipelineBuilder (void) { }
262 void bindShaderStage (VkShaderStageFlagBits stage,
263 const char* sourceName,
264 const char* entryName);
265 void enableTessellationStage (deUint32 patchControlPoints);
266 Move<VkPipeline> buildPipeline (tcu::UVec2 renderSize,
267 VkRenderPass renderPass,
268 VkPipelineCache cache,
269 VkPipelineLayout pipelineLayout,
270 VkPipelineCreateFlags flags);
271 void resetBuilder (void);
272
273 protected:
274 Context& m_context;
275
276 Move<VkShaderModule> m_shaderModules[VK_MAX_SHADER_STAGES];
277 deUint32 m_shaderStageCount;
278 VkPipelineShaderStageCreateInfo m_shaderStageInfo[VK_MAX_SHADER_STAGES];
279
280 deUint32 m_patchControlPoints;
281 };
282
SimpleGraphicsPipelineBuilder(Context & context)283 SimpleGraphicsPipelineBuilder::SimpleGraphicsPipelineBuilder (Context& context)
284 : m_context(context)
285 {
286 m_patchControlPoints = 0;
287 m_shaderStageCount = 0;
288 }
289
resetBuilder(void)290 void SimpleGraphicsPipelineBuilder::resetBuilder (void)
291 {
292 m_shaderStageCount = 0;
293 }
294
bindShaderStage(VkShaderStageFlagBits stage,const char * sourceName,const char * entryName)295 void SimpleGraphicsPipelineBuilder::bindShaderStage (VkShaderStageFlagBits stage,
296 const char* sourceName,
297 const char* entryName)
298 {
299 const DeviceInterface& vk = m_context.getDeviceInterface();
300 const VkDevice vkDevice = m_context.getDevice();
301
302 // Create shader module
303 deUint32* code = (deUint32*)m_context.getBinaryCollection().get(sourceName).getBinary();
304 deUint32 codeSize = (deUint32)m_context.getBinaryCollection().get(sourceName).getSize();
305
306 const VkShaderModuleCreateInfo moduleCreateInfo =
307 {
308 VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, // VkStructureType sType;
309 DE_NULL, // const void* pNext;
310 0u, // VkShaderModuleCreateFlags flags;
311 codeSize, // deUintptr codeSize;
312 code, // const deUint32* pCode;
313 };
314
315 m_shaderModules[m_shaderStageCount] = createShaderModule(vk, vkDevice, &moduleCreateInfo);
316
317 // Prepare shader stage info
318 m_shaderStageInfo[m_shaderStageCount].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
319 m_shaderStageInfo[m_shaderStageCount].pNext = DE_NULL;
320 m_shaderStageInfo[m_shaderStageCount].flags = 0u;
321 m_shaderStageInfo[m_shaderStageCount].stage = stage;
322 m_shaderStageInfo[m_shaderStageCount].module = *m_shaderModules[m_shaderStageCount];
323 m_shaderStageInfo[m_shaderStageCount].pName = entryName;
324 m_shaderStageInfo[m_shaderStageCount].pSpecializationInfo = DE_NULL;
325
326 m_shaderStageCount++;
327 }
328
buildPipeline(tcu::UVec2 renderSize,VkRenderPass renderPass,VkPipelineCache cache,VkPipelineLayout pipelineLayout,VkPipelineCreateFlags flags)329 Move<VkPipeline> SimpleGraphicsPipelineBuilder::buildPipeline (tcu::UVec2 renderSize, VkRenderPass renderPass, VkPipelineCache cache,
330 VkPipelineLayout pipelineLayout, VkPipelineCreateFlags flags)
331 {
332 const DeviceInterface& vk = m_context.getDeviceInterface();
333 const VkDevice vkDevice = m_context.getDevice();
334
335 // Create pipeline
336 const VkVertexInputBindingDescription vertexInputBindingDescription =
337 {
338 0u, // deUint32 binding;
339 sizeof(Vertex4RGBA), // deUint32 strideInBytes;
340 VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate;
341 };
342
343 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] =
344 {
345 {
346 0u, // deUint32 location;
347 0u, // deUint32 binding;
348 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
349 0u // deUint32 offsetInBytes;
350 },
351 {
352 1u, // deUint32 location;
353 0u, // deUint32 binding;
354 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
355 DE_OFFSET_OF(Vertex4RGBA, color), // deUint32 offsetInBytes;
356 }
357 };
358
359 const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
360 {
361 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
362 DE_NULL, // const void* pNext;
363 0u, // VkPipelineVertexInputStateCreateFlags flags;
364 1u, // deUint32 vertexBindingDescriptionCount;
365 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
366 2u, // deUint32 vertexAttributeDescriptionCount;
367 vertexInputAttributeDescriptions, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
368 };
369
370 const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateParams =
371 {
372 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
373 DE_NULL, // const void* pNext;
374 0u, // VkPipelineInputAssemblyStateCreateFlags flags;
375 (m_patchControlPoints == 0 ? VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST
376 : VK_PRIMITIVE_TOPOLOGY_PATCH_LIST), // VkPrimitiveTopology topology;
377 VK_FALSE, // VkBool32 primitiveRestartEnable;
378 };
379
380 const VkViewport viewport = makeViewport(renderSize);
381 const VkRect2D scissor = makeRect2D(renderSize);
382
383 const VkPipelineViewportStateCreateInfo viewportStateParams =
384 {
385 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
386 DE_NULL, // const void* pNext;
387 0u, // VkPipelineViewportStateCreateFlags flags;
388 1u, // deUint32 viewportCount;
389 &viewport, // const VkViewport* pViewports;
390 1u, // deUint32 scissorCount;
391 &scissor // const VkRect2D* pScissors;
392 };
393
394 const VkPipelineRasterizationStateCreateInfo rasterStateParams =
395 {
396 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
397 DE_NULL, // const void* pNext;
398 0u, // VkPipelineRasterizationStateCreateFlags flags;
399 VK_FALSE, // VkBool32 depthClampEnable;
400 VK_FALSE, // VkBool32 rasterizerDiscardEnable;
401 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode;
402 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode;
403 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
404 VK_FALSE, // VkBool32 depthBiasEnable;
405 0.0f, // float depthBiasConstantFactor;
406 0.0f, // float depthBiasClamp;
407 0.0f, // float depthBiasSlopeFactor;
408 1.0f, // float lineWidth;
409 };
410
411 const VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
412 {
413 VK_FALSE, // VkBool32 blendEnable;
414 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor;
415 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor;
416 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp;
417 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor;
418 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor;
419 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp;
420 VK_COLOR_COMPONENT_R_BIT |
421 VK_COLOR_COMPONENT_G_BIT |
422 VK_COLOR_COMPONENT_B_BIT |
423 VK_COLOR_COMPONENT_A_BIT // VkColorComponentFlags colorWriteMask;
424 };
425
426 const VkPipelineColorBlendStateCreateInfo colorBlendStateParams =
427 {
428 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
429 DE_NULL, // const void* pNext;
430 0u, // VkPipelineColorBlendStateCreateFlags flags;
431 VK_FALSE, // VkBool32 logicOpEnable;
432 VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
433 1u, // deUint32 attachmentCount;
434 &colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments;
435 { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConst[4];
436 };
437
438 const VkPipelineMultisampleStateCreateInfo multisampleStateParams =
439 {
440 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
441 DE_NULL, // const void* pNext;
442 0u, // VkPipelineMultisampleStateCreateFlags flags;
443 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
444 VK_FALSE, // VkBool32 sampleShadingEnable;
445 0.0f, // float minSampleShading;
446 DE_NULL, // const VkSampleMask* pSampleMask;
447 VK_FALSE, // VkBool32 alphaToCoverageEnable;
448 VK_FALSE, // VkBool32 alphaToOneEnable;
449 };
450
451 VkPipelineDepthStencilStateCreateInfo depthStencilStateParams =
452 {
453 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
454 DE_NULL, // const void* pNext;
455 0u, // VkPipelineDepthStencilStateCreateFlags flags;
456 VK_TRUE, // VkBool32 depthTestEnable;
457 VK_TRUE, // VkBool32 depthWriteEnable;
458 VK_COMPARE_OP_LESS_OR_EQUAL, // VkCompareOp depthCompareOp;
459 VK_FALSE, // VkBool32 depthBoundsTestEnable;
460 VK_FALSE, // VkBool32 stencilTestEnable;
461 // VkStencilOpState front;
462 {
463 VK_STENCIL_OP_KEEP, // VkStencilOp failOp;
464 VK_STENCIL_OP_KEEP, // VkStencilOp passOp;
465 VK_STENCIL_OP_KEEP, // VkStencilOp depthFailOp;
466 VK_COMPARE_OP_NEVER, // VkCompareOp compareOp;
467 0u, // deUint32 compareMask;
468 0u, // deUint32 writeMask;
469 0u, // deUint32 reference;
470 },
471 // VkStencilOpState back;
472 {
473 VK_STENCIL_OP_KEEP, // VkStencilOp failOp;
474 VK_STENCIL_OP_KEEP, // VkStencilOp passOp;
475 VK_STENCIL_OP_KEEP, // VkStencilOp depthFailOp;
476 VK_COMPARE_OP_NEVER, // VkCompareOp compareOp;
477 0u, // deUint32 compareMask;
478 0u, // deUint32 writeMask;
479 0u, // deUint32 reference;
480 },
481 0.0f, // float minDepthBounds;
482 1.0f, // float maxDepthBounds;
483 };
484
485 const VkPipelineTessellationStateCreateInfo tessStateCreateInfo =
486 {
487 VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, // VkStructureType sType;
488 DE_NULL, // const void* pNext;
489 0u, // VkPipelineTesselationStateCreateFlags flags;
490 m_patchControlPoints, // deUint32 patchControlPoints;
491 };
492 const VkPipelineTessellationStateCreateInfo* pTessCreateInfo = (m_patchControlPoints > 0)
493 ? &tessStateCreateInfo
494 : DE_NULL;
495
496 const VkGraphicsPipelineCreateInfo graphicsPipelineParams =
497 {
498 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
499 DE_NULL, // const void* pNext;
500 flags, // VkPipelineCreateFlags flags;
501 m_shaderStageCount, // deUint32 stageCount;
502 m_shaderStageInfo, // const VkPipelineShaderStageCreateInfo* pStages;
503 &vertexInputStateParams, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
504 &inputAssemblyStateParams, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
505 pTessCreateInfo, // const VkPipelineTessellationStateCreateInfo* pTessellationState;
506 &viewportStateParams, // const VkPipelineViewportStateCreateInfo* pViewportState;
507 &rasterStateParams, // const VkPipelineRasterizationStateCreateInfo* pRasterState;
508 &multisampleStateParams, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
509 &depthStencilStateParams, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
510 &colorBlendStateParams, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
511 (const VkPipelineDynamicStateCreateInfo*)DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState;
512 pipelineLayout, // VkPipelineLayout layout;
513 renderPass, // VkRenderPass renderPass;
514 0u, // deUint32 subpass;
515 DE_NULL, // VkPipeline basePipelineHandle;
516 0, // deInt32 basePipelineIndex;
517 };
518
519 return createGraphicsPipeline(vk, vkDevice, cache, &graphicsPipelineParams, DE_NULL);
520 }
521
enableTessellationStage(deUint32 patchControlPoints)522 void SimpleGraphicsPipelineBuilder::enableTessellationStage (deUint32 patchControlPoints)
523 {
524 m_patchControlPoints = patchControlPoints;
525 }
526
527 template <class Test>
newTestCase(tcu::TestContext & testContext,const ExecutablePropertiesTestParam * testParam)528 vkt::TestCase* newTestCase (tcu::TestContext& testContext,
529 const ExecutablePropertiesTestParam* testParam)
530 {
531 return new Test(testContext,
532 testParam->generateTestName().c_str(),
533 testParam->generateTestDescription().c_str(),
534 testParam);
535 }
536
537 // Test Classes
538 class ExecutablePropertiesTest : public vkt::TestCase
539 {
540 public:
ExecutablePropertiesTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,const ExecutablePropertiesTestParam * param)541 ExecutablePropertiesTest(tcu::TestContext& testContext,
542 const std::string& name,
543 const std::string& description,
544 const ExecutablePropertiesTestParam* param)
545 : vkt::TestCase (testContext, name, description)
546 , m_param (*param)
547 { }
~ExecutablePropertiesTest(void)548 virtual ~ExecutablePropertiesTest (void) { }
549 protected:
550 const ExecutablePropertiesTestParam m_param;
551 };
552
553 class ExecutablePropertiesTestInstance : public vkt::TestInstance
554 {
555 public:
556 ExecutablePropertiesTestInstance (Context& context,
557 const ExecutablePropertiesTestParam* param);
558 virtual ~ExecutablePropertiesTestInstance (void);
559 virtual tcu::TestStatus iterate (void);
560 protected:
561 virtual tcu::TestStatus verifyStatistics (deUint32 binaryNdx);
562 virtual tcu::TestStatus verifyInternalRepresentations (deUint32 binaryNdx);
563 virtual tcu::TestStatus verifyTestResult (void);
564 protected:
565 const ExecutablePropertiesTestParam* m_param;
566
567 Move<VkPipelineCache> m_cache;
568 deBool m_extensions;
569
570 Move<VkPipeline> m_pipeline[PIPELINE_CACHE_NDX_COUNT];
571 };
572
ExecutablePropertiesTestInstance(Context & context,const ExecutablePropertiesTestParam * param)573 ExecutablePropertiesTestInstance::ExecutablePropertiesTestInstance (Context& context,
574 const ExecutablePropertiesTestParam* param)
575 : TestInstance (context)
576 , m_param (param)
577 , m_extensions (m_context.requireDeviceFunctionality("VK_KHR_pipeline_executable_properties"))
578 {
579 const DeviceInterface& vk = m_context.getDeviceInterface();
580 const VkDevice vkDevice = m_context.getDevice();
581
582 const VkPipelineCacheCreateInfo pipelineCacheCreateInfo =
583 {
584 VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO, // VkStructureType sType;
585 DE_NULL, // const void* pNext;
586 0u, // VkPipelineCacheCreateFlags flags;
587 0u, // deUintptr initialDataSize;
588 DE_NULL, // const void* pInitialData;
589 };
590
591 m_cache = createPipelineCache(vk, vkDevice, &pipelineCacheCreateInfo);
592 }
593
~ExecutablePropertiesTestInstance(void)594 ExecutablePropertiesTestInstance::~ExecutablePropertiesTestInstance (void)
595 {
596 }
597
iterate(void)598 tcu::TestStatus ExecutablePropertiesTestInstance::iterate (void)
599 {
600 return verifyTestResult();
601 }
602
603 bool
checkString(const char * string,size_t size)604 checkString(const char *string, size_t size)
605 {
606 size_t i = 0;
607 for (; i < size; i++)
608 {
609 if (string[i] == 0)
610 {
611 break;
612 }
613 }
614
615 // The string needs to be non-empty and null terminated
616 if (i == 0 || i >= size)
617 {
618 return false;
619 }
620
621 return true;
622 }
623
verifyStatistics(deUint32 executableNdx)624 tcu::TestStatus ExecutablePropertiesTestInstance::verifyStatistics (deUint32 executableNdx)
625 {
626 const DeviceInterface& vk = m_context.getDeviceInterface();
627 const VkDevice vkDevice = m_context.getDevice();
628 tcu::TestLog &log = m_context.getTestContext().getLog();
629
630 std::vector<VkPipelineExecutableStatisticKHR> statistics[PIPELINE_CACHE_NDX_COUNT];
631
632 for (deUint32 ndx = 0; ndx < PIPELINE_CACHE_NDX_COUNT; ndx++)
633 {
634 const VkPipelineExecutableInfoKHR pipelineExecutableInfo =
635 {
636 VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INFO_KHR, // VkStructureType sType;
637 DE_NULL, // const void* pNext;
638 *m_pipeline[ndx], // VkPipeline pipeline;
639 executableNdx, // uint32_t executableIndex;
640 };
641
642 deUint32 statisticCount = 0;
643 VK_CHECK(vk.getPipelineExecutableStatisticsKHR(vkDevice, &pipelineExecutableInfo, &statisticCount, DE_NULL));
644
645 if (statisticCount == 0)
646 {
647 continue;
648 }
649
650 statistics[ndx].resize(statisticCount);
651 for (deUint32 statNdx = 0; statNdx < statisticCount; statNdx++)
652 {
653 deMemset(&statistics[ndx][statNdx], 0, sizeof(statistics[ndx][statNdx]));
654 statistics[ndx][statNdx].sType = VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_STATISTIC_KHR;
655 statistics[ndx][statNdx].pNext = DE_NULL;
656 }
657 VK_CHECK(vk.getPipelineExecutableStatisticsKHR(vkDevice, &pipelineExecutableInfo, &statisticCount, &statistics[ndx][0]));
658
659 for (deUint32 statNdx = 0; statNdx < statisticCount; statNdx++)
660 {
661 if (!checkString(statistics[ndx][statNdx].name, DE_LENGTH_OF_ARRAY(statistics[ndx][statNdx].name)))
662 {
663 return tcu::TestStatus::fail("Invalid statistic name string");
664 }
665
666 for (deUint32 otherNdx = 0; otherNdx < statNdx; otherNdx++)
667 {
668 if (deMemCmp(statistics[ndx][statNdx].name, statistics[ndx][otherNdx].name,
669 DE_LENGTH_OF_ARRAY(statistics[ndx][statNdx].name)) == 0)
670 {
671 return tcu::TestStatus::fail("Statistic name string not unique within the executable");
672 }
673 }
674
675 if (!checkString(statistics[ndx][statNdx].description, DE_LENGTH_OF_ARRAY(statistics[ndx][statNdx].description)))
676 {
677 return tcu::TestStatus::fail("Invalid statistic description string");
678 }
679
680 if (statistics[ndx][statNdx].format == VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_BOOL32_KHR)
681 {
682 if (statistics[ndx][statNdx].value.b32 != VK_TRUE && statistics[ndx][statNdx].value.b32 != VK_FALSE)
683 {
684 return tcu::TestStatus::fail("Boolean statistic is neither VK_TRUE nor VK_FALSE");
685 }
686 }
687 }
688 }
689
690 if (statistics[0].size() != statistics[1].size())
691 {
692 return tcu::TestStatus::fail("Identical pipelines have different numbers of statistics");
693 }
694
695 if (statistics[0].size() == 0)
696 {
697 return tcu::TestStatus::pass("No statistics reported");
698 }
699
700 // Both compiles had better have specified the same infos
701 for (deUint32 statNdx0 = 0; statNdx0 < statistics[0].size(); statNdx0++)
702 {
703 deUint32 statNdx1 = 0;
704 for (; statNdx1 < statistics[1].size(); statNdx1++)
705 {
706 if (deMemCmp(statistics[0][statNdx0].name, statistics[1][statNdx1].name,
707 DE_LENGTH_OF_ARRAY(statistics[0][statNdx0].name)) == 0)
708 {
709 break;
710 }
711 }
712 if (statNdx1 >= statistics[1].size())
713 {
714 return tcu::TestStatus::fail("Identical pipelines have different statistics");
715 }
716
717 if (deMemCmp(statistics[0][statNdx0].description, statistics[1][statNdx1].description,
718 DE_LENGTH_OF_ARRAY(statistics[0][statNdx0].description)) != 0)
719 {
720 return tcu::TestStatus::fail("Invalid binary description string");
721 }
722
723 if (statistics[0][statNdx0].format != statistics[1][statNdx1].format)
724 {
725 return tcu::TestStatus::fail("Identical pipelines have statistics with different formats");
726 }
727
728 switch (statistics[0][statNdx0].format)
729 {
730 case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_BOOL32_KHR:
731 {
732 bool match = statistics[0][statNdx0].value.b32 == statistics[1][statNdx1].value.b32;
733 log << tcu::TestLog::Message
734 << statistics[0][statNdx0].name << ": "
735 << (statistics[0][statNdx0].value.b32 ? "VK_TRUE" : "VK_FALSE")
736 << (match ? "" : " (non-deterministic)")
737 << " (" << statistics[0][statNdx0].description << ")"
738 << tcu::TestLog::EndMessage;
739 break;
740 }
741 case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_INT64_KHR:
742 {
743 bool match = statistics[0][statNdx0].value.i64 == statistics[1][statNdx1].value.i64;
744 log << tcu::TestLog::Message
745 << statistics[0][statNdx0].name << ": "
746 << statistics[0][statNdx0].value.i64
747 << (match ? "" : " (non-deterministic)")
748 << " (" << statistics[0][statNdx0].description << ")"
749 << tcu::TestLog::EndMessage;
750 break;
751 }
752 case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_UINT64_KHR:
753 {
754 bool match = statistics[0][statNdx0].value.u64 == statistics[1][statNdx1].value.u64;
755 log << tcu::TestLog::Message
756 << statistics[0][statNdx0].name << ": "
757 << statistics[0][statNdx0].value.u64
758 << (match ? "" : " (non-deterministic)")
759 << " (" << statistics[0][statNdx0].description << ")"
760 << tcu::TestLog::EndMessage;
761 break;
762 }
763 case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_FLOAT64_KHR:
764 {
765 bool match = statistics[0][statNdx0].value.f64 == statistics[1][statNdx1].value.f64;
766 log << tcu::TestLog::Message
767 << statistics[0][statNdx0].name << ": "
768 << statistics[0][statNdx0].value.f64
769 << (match ? "" : " (non-deterministic)")
770 << " (" << statistics[0][statNdx0].description << ")"
771 << tcu::TestLog::EndMessage;
772 break;
773 }
774 default:
775 return tcu::TestStatus::fail("Invalid statistic format");
776 }
777 }
778
779 return tcu::TestStatus::pass("Pass");
780 }
781
verifyInternalRepresentations(deUint32 executableNdx)782 tcu::TestStatus ExecutablePropertiesTestInstance::verifyInternalRepresentations (deUint32 executableNdx)
783 {
784 const DeviceInterface& vk = m_context.getDeviceInterface();
785 const VkDevice vkDevice = m_context.getDevice();
786 tcu::TestLog &log = m_context.getTestContext().getLog();
787
788 // We only care about internal representations on the second pipeline.
789 // We still compile twice to ensure that we still get the right thing
790 // even if the pipeline is hot in the cache.
791 const VkPipelineExecutableInfoKHR pipelineExecutableInfo =
792 {
793 VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INFO_KHR, // VkStructureType sType;
794 DE_NULL, // const void* pNext;
795 *m_pipeline[1], // VkPipeline pipeline;
796 executableNdx, // uint32_t executableIndex;
797 };
798
799 std::vector<VkPipelineExecutableInternalRepresentationKHR> irs;
800 std::vector<std::vector<deUint8>> irDatas;
801
802 deUint32 irCount = 0;
803 VK_CHECK(vk.getPipelineExecutableInternalRepresentationsKHR(vkDevice, &pipelineExecutableInfo, &irCount, DE_NULL));
804
805 if (irCount == 0)
806 {
807 return tcu::TestStatus::pass("No internal representations reported");
808 }
809
810 irs.resize(irCount);
811 irDatas.resize(irCount);
812 for (deUint32 irNdx = 0; irNdx < irCount; irNdx++)
813 {
814 deMemset(&irs[irNdx], 0, sizeof(irs[irNdx]));
815 irs[irNdx].sType = VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INTERNAL_REPRESENTATION_KHR;
816 irs[irNdx].pNext = DE_NULL;
817 }
818 VK_CHECK(vk.getPipelineExecutableInternalRepresentationsKHR(vkDevice, &pipelineExecutableInfo, &irCount, &irs[0]));
819
820 for (deUint32 irNdx = 0; irNdx < irCount; irNdx++)
821 {
822 if (!checkString(irs[irNdx].name, DE_LENGTH_OF_ARRAY(irs[irNdx].name)))
823 {
824 return tcu::TestStatus::fail("Invalid internal representation name string");
825 }
826
827 for (deUint32 otherNdx = 0; otherNdx < irNdx; otherNdx++)
828 {
829 if (deMemCmp(irs[irNdx].name, irs[otherNdx].name,
830 DE_LENGTH_OF_ARRAY(irs[irNdx].name)) == 0)
831 {
832 return tcu::TestStatus::fail("Internal representation name string not unique within the executable");
833 }
834 }
835
836 if (!checkString(irs[irNdx].description, DE_LENGTH_OF_ARRAY(irs[irNdx].description)))
837 {
838 return tcu::TestStatus::fail("Invalid binary description string");
839 }
840
841 if (irs[irNdx].dataSize == 0)
842 {
843 return tcu::TestStatus::fail("Internal representation has no data");
844 }
845
846 irDatas[irNdx].resize(irs[irNdx].dataSize);
847 irs[irNdx].pData = &irDatas[irNdx][0];
848 if (irs[irNdx].isText)
849 {
850 // For binary data the size is important. We check that the
851 // implementation fills the whole buffer by filling it with
852 // garbage first and then looking for that same garbage later.
853 for (size_t i = 0; i < irs[irNdx].dataSize; i++)
854 {
855 irDatas[irNdx][i] = (deUint8)(37 * (17 + i));
856 }
857 }
858 }
859
860 VK_CHECK(vk.getPipelineExecutableInternalRepresentationsKHR(vkDevice, &pipelineExecutableInfo, &irCount, &irs[0]));
861
862 for (deUint32 irNdx = 0; irNdx < irCount; irNdx++)
863 {
864 if (irs[irNdx].isText)
865 {
866 if (!checkString((char *)irs[irNdx].pData, irs[irNdx].dataSize))
867 {
868 return tcu::TestStatus::fail("Textual internal representation isn't a valid string");
869 }
870 log << tcu::TestLog::Section(irs[irNdx].name, irs[irNdx].description)
871 << tcu::LogKernelSource((char *)irs[irNdx].pData)
872 << tcu::TestLog::EndSection;
873 }
874 else
875 {
876 size_t maxMatchingChunkSize = 0;
877 size_t matchingChunkSize = 0;
878 for (size_t i = 0; i < irs[irNdx].dataSize; i++)
879 {
880 if (irDatas[irNdx][i] == (deUint8)(37 * (17 + i)))
881 {
882 matchingChunkSize++;
883 if (matchingChunkSize > maxMatchingChunkSize)
884 {
885 maxMatchingChunkSize = matchingChunkSize;
886 }
887 }
888 else
889 {
890 matchingChunkSize = 0;
891 }
892 }
893
894 // 64 bytes of our random data still being in the buffer probably
895 // isn't a coincidence
896 if (matchingChunkSize == irs[irNdx].dataSize || matchingChunkSize >= 64)
897 {
898 return tcu::TestStatus::fail("Implementation didn't fill the whole internal representation data buffer");
899 }
900
901 log << tcu::TestLog::Section(irs[irNdx].name, irs[irNdx].description)
902 << tcu::TestLog::Message << "Received " << irs[irNdx].dataSize << "B of binary data" << tcu::TestLog::EndMessage
903 << tcu::TestLog::EndSection;
904 }
905 }
906
907 return tcu::TestStatus::pass("Pass");
908 }
909
verifyTestResult(void)910 tcu::TestStatus ExecutablePropertiesTestInstance::verifyTestResult (void)
911 {
912 const DeviceInterface& vk = m_context.getDeviceInterface();
913 const VkDevice vkDevice = m_context.getDevice();
914 tcu::TestLog &log = m_context.getTestContext().getLog();
915
916 std::vector<VkPipelineExecutablePropertiesKHR> props[PIPELINE_CACHE_NDX_COUNT];
917
918 for (deUint32 ndx = 0; ndx < PIPELINE_CACHE_NDX_COUNT; ndx++)
919 {
920 const VkPipelineInfoKHR pipelineInfo =
921 {
922 VK_STRUCTURE_TYPE_PIPELINE_INFO_KHR, // VkStructureType sType;
923 DE_NULL, // const void* pNext;
924 *m_pipeline[ndx], // VkPipeline pipeline;
925
926 };
927 deUint32 executableCount = 0;
928 VK_CHECK(vk.getPipelineExecutablePropertiesKHR(vkDevice, &pipelineInfo, &executableCount, DE_NULL));
929
930 if (executableCount == 0)
931 {
932 continue;
933 }
934
935 props[ndx].resize(executableCount);
936 for (deUint32 execNdx = 0; execNdx < executableCount; execNdx++)
937 {
938 deMemset(&props[ndx][execNdx], 0, sizeof(props[ndx][execNdx]));
939 props[ndx][execNdx].sType = VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_PROPERTIES_KHR;
940 props[ndx][execNdx].pNext = DE_NULL;
941 }
942 VK_CHECK(vk.getPipelineExecutablePropertiesKHR(vkDevice, &pipelineInfo, &executableCount, &props[ndx][0]));
943
944 for (deUint32 execNdx = 0; execNdx < executableCount; execNdx++)
945 {
946 if (!checkString(props[ndx][execNdx].name, DE_LENGTH_OF_ARRAY(props[ndx][execNdx].name)))
947 {
948 return tcu::TestStatus::fail("Invalid binary name string");
949 }
950
951 for (deUint32 otherNdx = 0; otherNdx < execNdx; otherNdx++)
952 {
953 if (deMemCmp(props[ndx][execNdx].name, props[ndx][otherNdx].name,
954 DE_LENGTH_OF_ARRAY(props[ndx][execNdx].name)) == 0)
955 {
956 return tcu::TestStatus::fail("Binary name string not unique within the pipeline");
957 }
958 }
959
960 if (!checkString(props[ndx][execNdx].description, DE_LENGTH_OF_ARRAY(props[ndx][execNdx].description)))
961 {
962 return tcu::TestStatus::fail("Invalid binary description string");
963 }
964
965 // Check that the binary only contains stages actually used to
966 // compile the pipeline
967 VkShaderStageFlags stages = props[ndx][execNdx].stages;
968 for (deUint32 stageNdx = 0; stageNdx < m_param->getShaderCount(); stageNdx++)
969 {
970 stages &= ~m_param->getShaderFlag(stageNdx);
971 }
972 if (stages != 0)
973 {
974 return tcu::TestStatus::fail("Binary uses unprovided stage");
975 }
976 }
977 }
978
979 if (props[0].size() != props[1].size())
980 {
981 return tcu::TestStatus::fail("Identical pipelines have different numbers of props");
982 }
983
984 if (props[0].size() == 0)
985 {
986 return tcu::TestStatus::pass("No executables reported");
987 }
988
989 // Both compiles had better have specified the same infos
990 for (deUint32 execNdx0 = 0; execNdx0 < props[0].size(); execNdx0++)
991 {
992 deUint32 execNdx1 = 0;
993 for (; execNdx1 < props[1].size(); execNdx1++)
994 {
995 if (deMemCmp(props[0][execNdx0].name, props[1][execNdx1].name,
996 DE_LENGTH_OF_ARRAY(props[0][execNdx0].name)) == 0)
997 {
998 break;
999 }
1000 }
1001 if (execNdx1 >= props[1].size())
1002 {
1003 return tcu::TestStatus::fail("Identical pipelines have different sets of executables");
1004 }
1005
1006 if (deMemCmp(props[0][execNdx0].description, props[1][execNdx1].description,
1007 DE_LENGTH_OF_ARRAY(props[0][execNdx0].description)) != 0)
1008 {
1009 return tcu::TestStatus::fail("Same binary has different descriptions");
1010 }
1011
1012 if (props[0][execNdx0].stages != props[1][execNdx1].stages)
1013 {
1014 return tcu::TestStatus::fail("Same binary has different stages");
1015 }
1016
1017 if (props[0][execNdx0].subgroupSize != props[1][execNdx1].subgroupSize)
1018 {
1019 return tcu::TestStatus::fail("Same binary has different subgroup sizes");
1020 }
1021 }
1022
1023 log << tcu::TestLog::Section("Binaries", "Binaries reported for this pipeline");
1024 log << tcu::TestLog::Message << "Pipeline reported " << props[0].size() << " props" << tcu::TestLog::EndMessage;
1025
1026 tcu::TestStatus status = tcu::TestStatus::pass("Pass");
1027 for (deUint32 execNdx = 0; execNdx < props[0].size(); execNdx++)
1028 {
1029 log << tcu::TestLog::Section(props[0][execNdx].name, props[0][execNdx].description);
1030 log << tcu::TestLog::Message << "Name: " << props[0][execNdx].name << tcu::TestLog::EndMessage;
1031 log << tcu::TestLog::Message << "Description: " << props[0][execNdx].description << tcu::TestLog::EndMessage;
1032 log << tcu::TestLog::Message << "Stages: " << getShaderFlagsStr(props[0][execNdx].stages) << tcu::TestLog::EndMessage;
1033 log << tcu::TestLog::Message << "Subgroup Size: " << props[0][execNdx].subgroupSize << tcu::TestLog::EndMessage;
1034
1035 if (m_param->getTestStatistics())
1036 {
1037 status = verifyStatistics(execNdx);
1038 if (status.getCode() != QP_TEST_RESULT_PASS)
1039 {
1040 log << tcu::TestLog::EndSection;
1041 break;
1042 }
1043 }
1044
1045 if (m_param->getTestInternalRepresentations())
1046 {
1047 status = verifyInternalRepresentations(execNdx);
1048 if (status.getCode() != QP_TEST_RESULT_PASS)
1049 {
1050 log << tcu::TestLog::EndSection;
1051 break;
1052 }
1053 }
1054
1055 log << tcu::TestLog::EndSection;
1056 }
1057
1058 log << tcu::TestLog::EndSection;
1059
1060 return status;
1061 }
1062
1063 class GraphicsExecutablePropertiesTest : public ExecutablePropertiesTest
1064 {
1065 public:
GraphicsExecutablePropertiesTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,const ExecutablePropertiesTestParam * param)1066 GraphicsExecutablePropertiesTest (tcu::TestContext& testContext,
1067 const std::string& name,
1068 const std::string& description,
1069 const ExecutablePropertiesTestParam* param)
1070 : ExecutablePropertiesTest (testContext, name, description, param)
1071 { }
~GraphicsExecutablePropertiesTest(void)1072 virtual ~GraphicsExecutablePropertiesTest (void) { }
1073 virtual void initPrograms (SourceCollections& programCollection) const;
1074 virtual TestInstance* createInstance (Context& context) const;
1075 };
1076
1077 class GraphicsExecutablePropertiesTestInstance : public ExecutablePropertiesTestInstance
1078 {
1079 public:
1080 GraphicsExecutablePropertiesTestInstance (Context& context,
1081 const ExecutablePropertiesTestParam* param);
1082 virtual ~GraphicsExecutablePropertiesTestInstance (void);
1083 protected:
1084 const tcu::UVec2 m_renderSize;
1085 const VkFormat m_colorFormat;
1086 const VkFormat m_depthFormat;
1087 Move<VkPipelineLayout> m_pipelineLayout;
1088
1089 SimpleGraphicsPipelineBuilder m_pipelineBuilder;
1090 SimpleGraphicsPipelineBuilder m_missPipelineBuilder;
1091 Move<VkRenderPass> m_renderPass;
1092 };
1093
initPrograms(SourceCollections & programCollection) const1094 void GraphicsExecutablePropertiesTest::initPrograms (SourceCollections& programCollection) const
1095 {
1096 for (deUint32 shaderNdx = 0; shaderNdx < m_param.getShaderCount(); shaderNdx++)
1097 {
1098 switch(m_param.getShaderFlag(shaderNdx))
1099 {
1100 case VK_SHADER_STAGE_VERTEX_BIT:
1101 programCollection.glslSources.add("color_vert") << glu::VertexSource(
1102 "#version 310 es\n"
1103 "layout(location = 0) in vec4 position;\n"
1104 "layout(location = 1) in vec4 color;\n"
1105 "layout(location = 0) out highp vec4 vtxColor;\n"
1106 "void main (void)\n"
1107 "{\n"
1108 " gl_Position = position;\n"
1109 " vtxColor = color;\n"
1110 "}\n");
1111 break;
1112 case VK_SHADER_STAGE_FRAGMENT_BIT:
1113 programCollection.glslSources.add("color_frag") << glu::FragmentSource(
1114 "#version 310 es\n"
1115 "layout(location = 0) in highp vec4 vtxColor;\n"
1116 "layout(location = 0) out highp vec4 fragColor;\n"
1117 "void main (void)\n"
1118 "{\n"
1119 " fragColor = vtxColor;\n"
1120 "}\n");
1121 break;
1122
1123 case VK_SHADER_STAGE_GEOMETRY_BIT:
1124 programCollection.glslSources.add("dummy_geo") << glu::GeometrySource(
1125 "#version 450 \n"
1126 "layout(triangles) in;\n"
1127 "layout(triangle_strip, max_vertices = 3) out;\n"
1128 "layout(location = 0) in highp vec4 in_vtxColor[];\n"
1129 "layout(location = 0) out highp vec4 vtxColor;\n"
1130 "out gl_PerVertex { vec4 gl_Position; float gl_PointSize; };\n"
1131 "in gl_PerVertex { vec4 gl_Position; float gl_PointSize; } gl_in[];\n"
1132 "void main (void)\n"
1133 "{\n"
1134 " for(int ndx=0; ndx<3; ndx++)\n"
1135 " {\n"
1136 " gl_Position = gl_in[ndx].gl_Position;\n"
1137 " gl_PointSize = gl_in[ndx].gl_PointSize;\n"
1138 " vtxColor = in_vtxColor[ndx];\n"
1139 " EmitVertex();\n"
1140 " }\n"
1141 " EndPrimitive();\n"
1142 "}\n");
1143 break;
1144
1145 case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
1146 programCollection.glslSources.add("basic_tcs") << glu::TessellationControlSource(
1147 "#version 450 \n"
1148 "layout(vertices = 3) out;\n"
1149 "layout(location = 0) in highp vec4 color[];\n"
1150 "layout(location = 0) out highp vec4 vtxColor[];\n"
1151 "out gl_PerVertex { vec4 gl_Position; float gl_PointSize; } gl_out[3];\n"
1152 "in gl_PerVertex { vec4 gl_Position; float gl_PointSize; } gl_in[gl_MaxPatchVertices];\n"
1153 "void main()\n"
1154 "{\n"
1155 " gl_TessLevelOuter[0] = 4.0;\n"
1156 " gl_TessLevelOuter[1] = 4.0;\n"
1157 " gl_TessLevelOuter[2] = 4.0;\n"
1158 " gl_TessLevelInner[0] = 4.0;\n"
1159 " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
1160 " gl_out[gl_InvocationID].gl_PointSize = gl_in[gl_InvocationID].gl_PointSize;\n"
1161 " vtxColor[gl_InvocationID] = color[gl_InvocationID];\n"
1162 "}\n");
1163 break;
1164
1165 case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
1166 programCollection.glslSources.add("basic_tes") << glu::TessellationEvaluationSource(
1167 "#version 450 \n"
1168 "layout(triangles, fractional_even_spacing, ccw) in;\n"
1169 "layout(location = 0) in highp vec4 colors[];\n"
1170 "layout(location = 0) out highp vec4 vtxColor;\n"
1171 "out gl_PerVertex { vec4 gl_Position; float gl_PointSize; };\n"
1172 "in gl_PerVertex { vec4 gl_Position; float gl_PointSize; } gl_in[gl_MaxPatchVertices];\n"
1173 "void main() \n"
1174 "{\n"
1175 " float u = gl_TessCoord.x;\n"
1176 " float v = gl_TessCoord.y;\n"
1177 " float w = gl_TessCoord.z;\n"
1178 " vec4 pos = vec4(0);\n"
1179 " vec4 color = vec4(0);\n"
1180 " pos.xyz += u * gl_in[0].gl_Position.xyz;\n"
1181 " color.xyz += u * colors[0].xyz;\n"
1182 " pos.xyz += v * gl_in[1].gl_Position.xyz;\n"
1183 " color.xyz += v * colors[1].xyz;\n"
1184 " pos.xyz += w * gl_in[2].gl_Position.xyz;\n"
1185 " color.xyz += w * colors[2].xyz;\n"
1186 " pos.w = 1.0;\n"
1187 " color.w = 1.0;\n"
1188 " gl_Position = pos;\n"
1189 " gl_PointSize = gl_in[0].gl_PointSize;"
1190 " vtxColor = color;\n"
1191 "}\n");
1192 break;
1193
1194 default:
1195 DE_FATAL("Unknown Shader Stage!");
1196 break;
1197 }
1198 }
1199 }
1200
createInstance(Context & context) const1201 TestInstance* GraphicsExecutablePropertiesTest::createInstance (Context& context) const
1202 {
1203 return new GraphicsExecutablePropertiesTestInstance(context, &m_param);
1204 }
1205
GraphicsExecutablePropertiesTestInstance(Context & context,const ExecutablePropertiesTestParam * param)1206 GraphicsExecutablePropertiesTestInstance::GraphicsExecutablePropertiesTestInstance (Context& context,
1207 const ExecutablePropertiesTestParam* param)
1208 : ExecutablePropertiesTestInstance (context, param)
1209 , m_renderSize (32u, 32u)
1210 , m_colorFormat (VK_FORMAT_R8G8B8A8_UNORM)
1211 , m_depthFormat (VK_FORMAT_D16_UNORM)
1212 , m_pipelineBuilder (context)
1213 , m_missPipelineBuilder (context)
1214 {
1215 const DeviceInterface& vk = m_context.getDeviceInterface();
1216 const VkDevice vkDevice = m_context.getDevice();
1217
1218 // Create pipeline layout
1219 {
1220 const VkPipelineLayoutCreateInfo pipelineLayoutParams =
1221 {
1222 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
1223 DE_NULL, // const void* pNext;
1224 0u, // VkPipelineLayoutCreateFlags flags;
1225 0u, // deUint32 setLayoutCount;
1226 DE_NULL, // const VkDescriptorSetLayout* pSetLayouts;
1227 0u, // deUint32 pushConstantRangeCount;
1228 DE_NULL // const VkPushConstantRange* pPushConstantRanges;
1229 };
1230
1231 m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
1232 }
1233
1234 // Create render pass
1235 m_renderPass = makeRenderPass(vk, vkDevice, m_colorFormat, m_depthFormat);
1236
1237 // Bind shader stages
1238
1239 VkPhysicalDeviceFeatures features = m_context.getDeviceFeatures();
1240 for (deUint32 ndx = 0; ndx < PIPELINE_CACHE_NDX_COUNT; ndx++)
1241 {
1242 for (deUint32 shaderNdx = 0; shaderNdx < m_param->getShaderCount(); shaderNdx++)
1243 {
1244 switch(m_param->getShaderFlag(shaderNdx))
1245 {
1246 case VK_SHADER_STAGE_VERTEX_BIT:
1247 m_pipelineBuilder.bindShaderStage(VK_SHADER_STAGE_VERTEX_BIT, "color_vert", "main");
1248 break;
1249 case VK_SHADER_STAGE_FRAGMENT_BIT:
1250 m_pipelineBuilder.bindShaderStage(VK_SHADER_STAGE_FRAGMENT_BIT, "color_frag", "main");
1251 break;
1252 case VK_SHADER_STAGE_GEOMETRY_BIT:
1253 if (features.geometryShader == VK_FALSE)
1254 {
1255 TCU_THROW(NotSupportedError, "Geometry Shader Not Supported");
1256 }
1257 else
1258 {
1259 m_pipelineBuilder.bindShaderStage(VK_SHADER_STAGE_GEOMETRY_BIT, "dummy_geo", "main");
1260 }
1261 break;
1262 case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
1263 if (features.tessellationShader == VK_FALSE)
1264 {
1265 TCU_THROW(NotSupportedError, "Tessellation Not Supported");
1266 }
1267 else
1268 {
1269 m_pipelineBuilder.bindShaderStage(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, "basic_tcs", "main");
1270 m_pipelineBuilder.enableTessellationStage(3);
1271 }
1272 break;
1273 case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
1274 if (features.tessellationShader == VK_FALSE)
1275 {
1276 TCU_THROW(NotSupportedError, "Tessellation Not Supported");
1277 }
1278 else
1279 {
1280 m_pipelineBuilder.bindShaderStage(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, "basic_tes", "main");
1281 m_pipelineBuilder.enableTessellationStage(3);
1282 }
1283 break;
1284 default:
1285 DE_FATAL("Unknown Shader Stage!");
1286 break;
1287 }
1288
1289 }
1290
1291 VkPipelineCreateFlags flags = 0;
1292 if (param->getTestStatistics())
1293 {
1294 flags |= VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR;
1295 }
1296
1297 // Only check gather internal representations on the second
1298 // pipeline. This way, it's more obvious if they failed to capture
1299 // due to the pipeline being cached.
1300 if (ndx == PIPELINE_CACHE_NDX_CACHED && param->getTestInternalRepresentations())
1301 {
1302 flags |= VK_PIPELINE_CREATE_CAPTURE_INTERNAL_REPRESENTATIONS_BIT_KHR;
1303 }
1304
1305 m_pipeline[ndx] = m_pipelineBuilder.buildPipeline(m_renderSize, *m_renderPass, *m_cache, *m_pipelineLayout, flags);
1306 m_pipelineBuilder.resetBuilder();
1307 }
1308 }
1309
~GraphicsExecutablePropertiesTestInstance(void)1310 GraphicsExecutablePropertiesTestInstance::~GraphicsExecutablePropertiesTestInstance (void)
1311 {
1312 }
1313
1314 class ComputeExecutablePropertiesTest : public ExecutablePropertiesTest
1315 {
1316 public:
ComputeExecutablePropertiesTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,const ExecutablePropertiesTestParam * param)1317 ComputeExecutablePropertiesTest (tcu::TestContext& testContext,
1318 const std::string& name,
1319 const std::string& description,
1320 const ExecutablePropertiesTestParam* param)
1321 : ExecutablePropertiesTest (testContext, name, description, param)
1322 { }
~ComputeExecutablePropertiesTest(void)1323 virtual ~ComputeExecutablePropertiesTest (void) { }
1324 virtual void initPrograms (SourceCollections& programCollection) const;
1325 virtual TestInstance* createInstance (Context& context) const;
1326 };
1327
1328 class ComputeExecutablePropertiesTestInstance : public ExecutablePropertiesTestInstance
1329 {
1330 public:
1331 ComputeExecutablePropertiesTestInstance (Context& context,
1332 const ExecutablePropertiesTestParam* param);
1333 virtual ~ComputeExecutablePropertiesTestInstance (void);
1334 protected:
1335 void buildDescriptorSets (deUint32 ndx);
1336 void buildShader (deUint32 ndx);
1337 void buildPipeline (deUint32 ndx);
1338 protected:
1339 Move<VkBuffer> m_inputBuf;
1340 de::MovePtr<Allocation> m_inputBufferAlloc;
1341 Move<VkShaderModule> m_computeShaderModule[PIPELINE_CACHE_NDX_COUNT];
1342
1343 Move<VkBuffer> m_outputBuf[PIPELINE_CACHE_NDX_COUNT];
1344 de::MovePtr<Allocation> m_outputBufferAlloc[PIPELINE_CACHE_NDX_COUNT];
1345
1346 Move<VkDescriptorPool> m_descriptorPool[PIPELINE_CACHE_NDX_COUNT];
1347 Move<VkDescriptorSetLayout> m_descriptorSetLayout[PIPELINE_CACHE_NDX_COUNT];
1348 Move<VkDescriptorSet> m_descriptorSet[PIPELINE_CACHE_NDX_COUNT];
1349
1350 Move<VkPipelineLayout> m_pipelineLayout[PIPELINE_CACHE_NDX_COUNT];
1351 };
1352
initPrograms(SourceCollections & programCollection) const1353 void ComputeExecutablePropertiesTest::initPrograms (SourceCollections& programCollection) const
1354 {
1355 programCollection.glslSources.add("basic_compute") << glu::ComputeSource(
1356 "#version 310 es\n"
1357 "layout(local_size_x = 1) in;\n"
1358 "layout(std430) buffer;\n"
1359 "layout(binding = 0) readonly buffer Input0\n"
1360 "{\n"
1361 " vec4 elements[];\n"
1362 "} input_data0;\n"
1363 "layout(binding = 1) writeonly buffer Output\n"
1364 "{\n"
1365 " vec4 elements[];\n"
1366 "} output_data;\n"
1367 "void main()\n"
1368 "{\n"
1369 " uint ident = gl_GlobalInvocationID.x;\n"
1370 " output_data.elements[ident] = input_data0.elements[ident] * input_data0.elements[ident];\n"
1371 "}");
1372 }
1373
createInstance(Context & context) const1374 TestInstance* ComputeExecutablePropertiesTest::createInstance (Context& context) const
1375 {
1376 return new ComputeExecutablePropertiesTestInstance(context, &m_param);
1377 }
1378
buildDescriptorSets(deUint32 ndx)1379 void ComputeExecutablePropertiesTestInstance::buildDescriptorSets (deUint32 ndx)
1380 {
1381 const DeviceInterface& vk = m_context.getDeviceInterface();
1382 const VkDevice vkDevice = m_context.getDevice();
1383
1384 // Create descriptor set layout
1385 DescriptorSetLayoutBuilder descLayoutBuilder;
1386 for (deUint32 bindingNdx = 0u; bindingNdx < 2u; bindingNdx++)
1387 descLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT);
1388 m_descriptorSetLayout[ndx] = descLayoutBuilder.build(vk, vkDevice);
1389 }
1390
buildShader(deUint32 ndx)1391 void ComputeExecutablePropertiesTestInstance::buildShader (deUint32 ndx)
1392 {
1393 const DeviceInterface& vk = m_context.getDeviceInterface();
1394 const VkDevice vkDevice = m_context.getDevice();
1395
1396 // Create compute shader
1397 VkShaderModuleCreateInfo shaderModuleCreateInfo =
1398 {
1399 VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, // VkStructureType sType;
1400 DE_NULL, // const void* pNext;
1401 0u, // VkShaderModuleCreateFlags flags;
1402 m_context.getBinaryCollection().get("basic_compute").getSize(), // deUintptr codeSize;
1403 (deUint32*)m_context.getBinaryCollection().get("basic_compute").getBinary(), // const deUint32* pCode;
1404 };
1405 m_computeShaderModule[ndx] = createShaderModule(vk, vkDevice, &shaderModuleCreateInfo);
1406 }
1407
buildPipeline(deUint32 ndx)1408 void ComputeExecutablePropertiesTestInstance::buildPipeline (deUint32 ndx)
1409 {
1410 const DeviceInterface& vk = m_context.getDeviceInterface();
1411 const VkDevice vkDevice = m_context.getDevice();
1412
1413 // Create compute pipeline layout
1414 const VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo =
1415 {
1416 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
1417 DE_NULL, // const void* pNext;
1418 0u, // VkPipelineLayoutCreateFlags flags;
1419 1u, // deUint32 setLayoutCount;
1420 &m_descriptorSetLayout[ndx].get(), // const VkDescriptorSetLayout* pSetLayouts;
1421 0u, // deUint32 pushConstantRangeCount;
1422 DE_NULL, // const VkPushConstantRange* pPushConstantRanges;
1423 };
1424
1425 m_pipelineLayout[ndx] = createPipelineLayout(vk, vkDevice, &pipelineLayoutCreateInfo);
1426
1427 const VkPipelineShaderStageCreateInfo stageCreateInfo =
1428 {
1429 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
1430 DE_NULL, // const void* pNext;
1431 0u, // VkPipelineShaderStageCreateFlags flags;
1432 VK_SHADER_STAGE_COMPUTE_BIT, // VkShaderStageFlagBits stage;
1433 *m_computeShaderModule[ndx], // VkShaderModule module;
1434 "main", // const char* pName;
1435 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
1436 };
1437
1438 VkPipelineCreateFlags flags = 0;
1439 if (m_param->getTestStatistics())
1440 {
1441 flags |= VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR;
1442 }
1443
1444 // Only check gather internal representations on the second
1445 // pipeline. This way, it's more obvious if they failed to capture
1446 // due to the pipeline being cached.
1447 if (ndx == PIPELINE_CACHE_NDX_CACHED && m_param->getTestInternalRepresentations())
1448 {
1449 flags |= VK_PIPELINE_CREATE_CAPTURE_INTERNAL_REPRESENTATIONS_BIT_KHR;
1450 }
1451
1452 const VkComputePipelineCreateInfo pipelineCreateInfo =
1453 {
1454 VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, // VkStructureType sType;
1455 DE_NULL, // const void* pNext;
1456 flags, // VkPipelineCreateFlags flags;
1457 stageCreateInfo, // VkPipelineShaderStageCreateInfo stage;
1458 *m_pipelineLayout[ndx], // VkPipelineLayout layout;
1459 (VkPipeline)0, // VkPipeline basePipelineHandle;
1460 0u, // deInt32 basePipelineIndex;
1461 };
1462
1463 m_pipeline[ndx] = createComputePipeline(vk, vkDevice, *m_cache, &pipelineCreateInfo, DE_NULL);
1464 }
1465
ComputeExecutablePropertiesTestInstance(Context & context,const ExecutablePropertiesTestParam * param)1466 ComputeExecutablePropertiesTestInstance::ComputeExecutablePropertiesTestInstance (Context& context,
1467 const ExecutablePropertiesTestParam* param)
1468 : ExecutablePropertiesTestInstance (context, param)
1469 {
1470 for (deUint32 ndx = 0; ndx < PIPELINE_CACHE_NDX_COUNT; ndx++)
1471 {
1472 buildDescriptorSets(ndx);
1473 buildShader(ndx);
1474 buildPipeline(ndx);
1475 }
1476 }
1477
~ComputeExecutablePropertiesTestInstance(void)1478 ComputeExecutablePropertiesTestInstance::~ComputeExecutablePropertiesTestInstance (void)
1479 {
1480 }
1481
1482 } // anonymous
1483
createExecutablePropertiesTests(tcu::TestContext & testCtx)1484 tcu::TestCaseGroup* createExecutablePropertiesTests (tcu::TestContext& testCtx)
1485 {
1486
1487 de::MovePtr<tcu::TestCaseGroup> binaryInfoTests (new tcu::TestCaseGroup(testCtx, "executable_properties", "pipeline binary statistics tests"));
1488
1489 // Graphics Pipeline Tests
1490 {
1491 de::MovePtr<tcu::TestCaseGroup> graphicsTests (new tcu::TestCaseGroup(testCtx, "graphics", "Test pipeline binary info with graphics pipeline."));
1492
1493 const VkShaderStageFlagBits testParamShaders0[] =
1494 {
1495 VK_SHADER_STAGE_VERTEX_BIT,
1496 VK_SHADER_STAGE_FRAGMENT_BIT,
1497 };
1498 const VkShaderStageFlagBits testParamShaders1[] =
1499 {
1500 VK_SHADER_STAGE_VERTEX_BIT,
1501 VK_SHADER_STAGE_GEOMETRY_BIT,
1502 VK_SHADER_STAGE_FRAGMENT_BIT,
1503 };
1504 const VkShaderStageFlagBits testParamShaders2[] =
1505 {
1506 VK_SHADER_STAGE_VERTEX_BIT,
1507 VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
1508 VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
1509 VK_SHADER_STAGE_FRAGMENT_BIT,
1510 };
1511 const ExecutablePropertiesTestParam testParams[] =
1512 {
1513 ExecutablePropertiesTestParam(testParamShaders0, DE_LENGTH_OF_ARRAY(testParamShaders0), DE_FALSE, DE_FALSE),
1514 ExecutablePropertiesTestParam(testParamShaders1, DE_LENGTH_OF_ARRAY(testParamShaders1), DE_FALSE, DE_FALSE),
1515 ExecutablePropertiesTestParam(testParamShaders2, DE_LENGTH_OF_ARRAY(testParamShaders2), DE_FALSE, DE_FALSE),
1516 ExecutablePropertiesTestParam(testParamShaders0, DE_LENGTH_OF_ARRAY(testParamShaders0), DE_TRUE, DE_FALSE),
1517 ExecutablePropertiesTestParam(testParamShaders1, DE_LENGTH_OF_ARRAY(testParamShaders1), DE_TRUE, DE_FALSE),
1518 ExecutablePropertiesTestParam(testParamShaders2, DE_LENGTH_OF_ARRAY(testParamShaders2), DE_TRUE, DE_FALSE),
1519 ExecutablePropertiesTestParam(testParamShaders0, DE_LENGTH_OF_ARRAY(testParamShaders0), DE_FALSE, DE_TRUE),
1520 ExecutablePropertiesTestParam(testParamShaders1, DE_LENGTH_OF_ARRAY(testParamShaders1), DE_FALSE, DE_TRUE),
1521 ExecutablePropertiesTestParam(testParamShaders2, DE_LENGTH_OF_ARRAY(testParamShaders2), DE_FALSE, DE_TRUE),
1522 ExecutablePropertiesTestParam(testParamShaders0, DE_LENGTH_OF_ARRAY(testParamShaders0), DE_TRUE, DE_TRUE),
1523 ExecutablePropertiesTestParam(testParamShaders1, DE_LENGTH_OF_ARRAY(testParamShaders1), DE_TRUE, DE_TRUE),
1524 ExecutablePropertiesTestParam(testParamShaders2, DE_LENGTH_OF_ARRAY(testParamShaders2), DE_TRUE, DE_TRUE),
1525 };
1526
1527 for (deUint32 i = 0; i < DE_LENGTH_OF_ARRAY(testParams); i++)
1528 graphicsTests->addChild(newTestCase<GraphicsExecutablePropertiesTest>(testCtx, &testParams[i]));
1529
1530 binaryInfoTests->addChild(graphicsTests.release());
1531 }
1532
1533 // Compute Pipeline Tests
1534 {
1535 de::MovePtr<tcu::TestCaseGroup> computeTests (new tcu::TestCaseGroup(testCtx, "compute", "Test pipeline binary info with compute pipeline."));
1536
1537 const VkShaderStageFlagBits testParamShaders0[] =
1538 {
1539 VK_SHADER_STAGE_COMPUTE_BIT,
1540 };
1541 const ExecutablePropertiesTestParam testParams[] =
1542 {
1543 ExecutablePropertiesTestParam(testParamShaders0, DE_LENGTH_OF_ARRAY(testParamShaders0), DE_FALSE, DE_FALSE),
1544 ExecutablePropertiesTestParam(testParamShaders0, DE_LENGTH_OF_ARRAY(testParamShaders0), DE_TRUE, DE_FALSE),
1545 ExecutablePropertiesTestParam(testParamShaders0, DE_LENGTH_OF_ARRAY(testParamShaders0), DE_FALSE, DE_TRUE),
1546 ExecutablePropertiesTestParam(testParamShaders0, DE_LENGTH_OF_ARRAY(testParamShaders0), DE_TRUE, DE_TRUE),
1547 };
1548
1549 for (deUint32 i = 0; i < DE_LENGTH_OF_ARRAY(testParams); i++)
1550 computeTests->addChild(newTestCase<ComputeExecutablePropertiesTest>(testCtx, &testParams[i]));
1551
1552 binaryInfoTests->addChild(computeTests.release());
1553 }
1554
1555 return binaryInfoTests.release();
1556 }
1557
1558 } // pipeline
1559
1560 } // vkt
1561