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