1/*------------------------------------------------------------------------ 2 * Vulkan Conformance Tests 3 * ------------------------ 4 * 5 * Copyright (c) 2016 The Khronos Group Inc. 6 * Copyright (c) 2023 LunarG, Inc. 7 * Copyright (c) 2023 Nintendo 8 * 9 * Licensed under the Apache License, Version 2.0 (the "License"); 10 * you may not use this file except in compliance with the License. 11 * You may obtain a copy of the License at 12 * 13 * http://www.apache.org/licenses/LICENSE-2.0 14 * 15 * Unless required by applicable law or agreed to in writing, software 16 * distributed under the License is distributed on an "AS IS" BASIS, 17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 * See the License for the specific language governing permissions and 19 * limitations under the License. 20 * 21 *//*! 22 * \file 23 * \brief Pipeline specialization constants tests 24 *//*--------------------------------------------------------------------*/ 25 26#include "vktPipelineSpecConstantTests.hpp" 27#include "vktTestCase.hpp" 28#include "vktPipelineSpecConstantUtil.hpp" 29#include "vktPipelineMakeUtil.hpp" 30 31#include "tcuTestLog.hpp" 32#include "tcuTexture.hpp" 33#include "tcuFormatUtil.hpp" 34#include "tcuFloat.hpp" 35 36#include "gluShaderUtil.hpp" 37 38#include "vkBuilderUtil.hpp" 39#include "vkPrograms.hpp" 40#include "vkRefUtil.hpp" 41#include "vkTypeUtil.hpp" 42#include "vkImageUtil.hpp" 43#include "vkBarrierUtil.hpp" 44#include "vkCmdUtil.hpp" 45#include "vkObjUtil.hpp" 46#include "vkBufferWithMemory.hpp" 47#include "vkImageWithMemory.hpp" 48#include "vkComputePipelineConstructionUtil.hpp" 49 50#include "deUniquePtr.hpp" 51#include "deStringUtil.hpp" 52 53#include <limits> 54 55namespace vkt 56{ 57namespace pipeline 58{ 59 60using namespace vk; 61 62namespace 63{ 64 65static const char* const s_perVertexBlock = "gl_PerVertex {\n" 66 " vec4 gl_Position;\n" 67 "}"; 68 69//! Raw memory storage for values used in test cases. 70//! We use it to simplify test case definitions where different types are expected in the result. 71class GenericValue 72{ 73public: 74 GenericValue (void) { clear(); } 75 76 //! Copy up to 'size' bytes of 'data'. 77 GenericValue (const void* data, const deUint32 size) 78 { 79 DE_ASSERT(size <= sizeof(m_data)); 80 clear(); 81 deMemcpy(&m_data, data, size); 82 } 83 84private: 85 deUint64 m_data; 86 87 void clear (void) { m_data = 0; } 88}; 89 90inline GenericValue makeValueBool32 (const bool a) { return GenericValue(&a, sizeof(a)); } 91inline GenericValue makeValueInt8 (const deInt8 a) { return GenericValue(&a, sizeof(a)); } 92inline GenericValue makeValueUint8 (const deUint8 a) { return GenericValue(&a, sizeof(a)); } 93inline GenericValue makeValueInt16 (const deInt16 a) { return GenericValue(&a, sizeof(a)); } 94inline GenericValue makeValueUint16 (const deUint16 a) { return GenericValue(&a, sizeof(a)); } 95inline GenericValue makeValueInt32 (const deInt32 a) { return GenericValue(&a, sizeof(a)); } 96inline GenericValue makeValueUint32 (const deUint32 a) { return GenericValue(&a, sizeof(a)); } 97inline GenericValue makeValueInt64 (const deInt64 a) { return GenericValue(&a, sizeof(a)); } 98inline GenericValue makeValueUint64 (const deUint64 a) { return GenericValue(&a, sizeof(a)); } 99inline GenericValue makeValueFloat16 (const tcu::Float16 a) { return GenericValue(&a, sizeof(a)); } 100inline GenericValue makeValueFloat32 (const float a) { return GenericValue(&a, sizeof(a)); } 101inline GenericValue makeValueFloat64 (const double a) { return GenericValue(&a, sizeof(a)); } 102 103struct SpecConstant 104{ 105 deUint32 specID; //!< specialization constant ID 106 std::string declarationCode; //!< syntax to declare the constant, use ${ID} as an ID placeholder 107 deUint32 size; //!< data size on the host, 0 = no specialized value 108 GenericValue specValue; //!< specialized value passed by the API 109 bool forceUse; //!< always include a VkSpecializationMapEntry for this spec constant 110 111 SpecConstant (const deUint32 specID_, const std::string declarationCode_) 112 : specID (specID_) 113 , declarationCode (declarationCode_) 114 , size (0) 115 , specValue () 116 , forceUse (false) 117 { 118 } 119 120 SpecConstant (const deUint32 specID_, const std::string declarationCode_, const deUint32 size_, const GenericValue specValue_, bool forceUse_ = false) 121 : specID (specID_) 122 , declarationCode (declarationCode_) 123 , size (size_) 124 , specValue (specValue_) 125 , forceUse (forceUse_) 126 { 127 } 128}; 129 130//! Useful when referring to a value in a buffer (i.e. check expected values in SSBO). 131struct OffsetValue 132{ 133 deUint32 size; //!< data size in the buffer (up to sizeof(value)) 134 deUint32 offset; //!< offset into the buffer 135 GenericValue value; //!< value expected to be there 136 137 OffsetValue (const deUint32 size_, const deUint32 offset_, const GenericValue value_) 138 : size (size_) 139 , offset (offset_) 140 , value (value_) 141 {} 142}; 143 144//! Get the integer value of 'size' bytes at 'memory' location. 145deUint64 memoryAsInteger (const void* memory, const deUint32 size) 146{ 147 DE_ASSERT(size <= sizeof(deUint64)); 148 deUint64 value = 0; 149 deMemcpy(&value, memory, size); 150 return value; 151} 152 153inline std::string memoryAsHexString (const void* memory, const deUint32 size) 154{ 155 const deUint8* memoryBytePtr = static_cast<const deUint8*>(memory); 156 return de::toString(tcu::formatArray(tcu::Format::HexIterator<deUint8>(memoryBytePtr), tcu::Format::HexIterator<deUint8>(memoryBytePtr + size))); 157} 158 159void logValueMismatch (tcu::TestLog& log, const void* expected, const void* actual, const deUint32 offset, const deUint32 size) 160{ 161 const bool canDisplayValue = (size <= sizeof(deUint64)); 162 log << tcu::TestLog::Message 163 << "Comparison failed for value at offset " << de::toString(offset) << ": expected " 164 << (canDisplayValue ? de::toString(memoryAsInteger(expected, size)) + " " : "") << memoryAsHexString(expected, size) << " but got " 165 << (canDisplayValue ? de::toString(memoryAsInteger(actual, size)) + " " : "") << memoryAsHexString(actual, size) 166 << tcu::TestLog::EndMessage; 167} 168 169//! Check if expected values exist in the memory. 170bool verifyValues (tcu::TestLog& log, const void* memory, const std::vector<OffsetValue>& expectedValues) 171{ 172 bool ok = true; 173 log << tcu::TestLog::Section("compare", "Verify result values"); 174 175 for (std::vector<OffsetValue>::const_iterator it = expectedValues.begin(); it < expectedValues.end(); ++it) 176 { 177 const char* const valuePtr = static_cast<const char*>(memory) + it->offset; 178 if (deMemCmp(valuePtr, &it->value, it->size) != 0) 179 { 180 ok = false; 181 logValueMismatch(log, &it->value, valuePtr, it->offset, it->size); 182 } 183 } 184 185 if (ok) 186 log << tcu::TestLog::Message << "All OK" << tcu::TestLog::EndMessage; 187 188 log << tcu::TestLog::EndSection; 189 return ok; 190} 191 192//! Bundles together common test case parameters. 193struct CaseDefinition 194{ 195 std::string name; //!< Test case name 196 std::vector<SpecConstant> specConstants; //!< list of specialization constants to declare 197 VkDeviceSize ssboSize; //!< required ssbo size in bytes 198 std::string ssboCode; //!< ssbo member definitions 199 std::string globalCode; //!< generic shader code outside the main function (e.g. declarations) 200 std::string mainCode; //!< generic shader code to execute in main (e.g. assignments) 201 std::vector<OffsetValue> expectedValues; //!< list of values to check inside the ssbo buffer 202 FeatureFlags requirements; //!< features the implementation must support to allow this test to run 203 bool packData; //!< whether to tightly pack specialization constant data or not 204}; 205 206//! Manages Vulkan structures to pass specialization data. 207class Specialization 208{ 209public: 210 Specialization (const std::vector<SpecConstant>& specConstants, bool packData); 211 212 //! Can return NULL if nothing is specialized 213 const VkSpecializationInfo* getSpecializationInfo (void) const { return m_entries.size() > 0 ? &m_specialization : DE_NULL; } 214 215private: 216 std::vector<deUint8> m_data; 217 std::vector<VkSpecializationMapEntry> m_entries; 218 VkSpecializationInfo m_specialization; 219}; 220 221Specialization::Specialization (const std::vector<SpecConstant>& specConstants, bool packData) 222{ 223 const auto kGenericValueSize = static_cast<deUint32>(sizeof(GenericValue)); 224 225 // Reserve memory for the worst case in m_data. 226 m_data.resize(specConstants.size() * kGenericValueSize, std::numeric_limits<deUint8>::max()); 227 m_entries.reserve(specConstants.size()); 228 229 deUint32 offset = 0u; 230 for (const auto& sc : specConstants) 231 { 232 if (sc.size != 0u || sc.forceUse) 233 { 234 if (sc.size > 0u) 235 deMemcpy(&m_data[offset], &sc.specValue, sc.size); 236 m_entries.push_back(makeSpecializationMapEntry(sc.specID, offset, sc.size)); 237 offset += (packData ? sc.size : kGenericValueSize); 238 } 239 } 240 241 if (m_entries.size() > 0) 242 { 243 m_specialization.mapEntryCount = static_cast<deUint32>(m_entries.size()); 244 m_specialization.pMapEntries = m_entries.data(); 245 m_specialization.dataSize = static_cast<deUintptr>(offset); 246 m_specialization.pData = m_data.data(); 247 } 248 else 249 deMemset(&m_specialization, 0, sizeof(m_specialization)); 250} 251 252class SpecConstantTest : public TestCase 253{ 254public: 255 SpecConstantTest (tcu::TestContext& testCtx, 256 const PipelineConstructionType pipelineType, //!< how pipeline is constructed 257 const VkShaderStageFlagBits stage, //!< which shader stage is tested 258 const CaseDefinition& caseDef); 259 260 void initPrograms (SourceCollections& programCollection) const; 261 TestInstance* createInstance (Context& context) const; 262 virtual void checkSupport (Context& context) const; 263 264private: 265 const PipelineConstructionType m_pipelineConstructionType; 266 const VkShaderStageFlagBits m_stage; 267 const CaseDefinition m_caseDef; 268}; 269 270SpecConstantTest::SpecConstantTest (tcu::TestContext& testCtx, 271 const PipelineConstructionType pipelineType, 272 const VkShaderStageFlagBits stage, 273 const CaseDefinition& caseDef) 274 : TestCase (testCtx, caseDef.name) 275 , m_pipelineConstructionType (pipelineType) 276 , m_stage (stage) 277 , m_caseDef (caseDef) 278{ 279} 280 281//! Build a string that declares all specialization constants, replacing ${ID} with proper ID numbers. 282std::string generateSpecConstantCode (const std::vector<SpecConstant>& specConstants) 283{ 284 std::ostringstream code; 285 for (std::vector<SpecConstant>::const_iterator it = specConstants.begin(); it != specConstants.end(); ++it) 286 { 287 std::string decl = it->declarationCode; 288 const std::string::size_type pos = decl.find("${ID}"); 289 if (pos != std::string::npos) 290 decl.replace(pos, 5, de::toString(it->specID)); 291 code << decl << "\n"; 292 } 293 code << "\n"; 294 return code.str(); 295} 296 297std::string generateSSBOCode (const std::string& memberDeclarations) 298{ 299 std::ostringstream code; 300 code << "layout (set = 0, binding = 0, std430) writeonly buffer Output {\n" 301 << memberDeclarations 302 << "} sb_out;\n" 303 << "\n"; 304 return code.str(); 305} 306 307void SpecConstantTest::initPrograms (SourceCollections& programCollection) const 308{ 309 // Always add vertex and fragment to graphics stages 310 VkShaderStageFlags requiredStages = m_stage; 311 312 if (requiredStages & VK_SHADER_STAGE_ALL_GRAPHICS) 313 requiredStages |= VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT; 314 315 if (requiredStages & (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)) 316 requiredStages |= VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT; 317 318 // Either graphics or compute must be defined, but not both 319 DE_ASSERT(((requiredStages & VK_SHADER_STAGE_ALL_GRAPHICS) != 0) != ((requiredStages & VK_SHADER_STAGE_COMPUTE_BIT) != 0)); 320 321 // Extensions needed for some tests. 322 std::ostringstream extStream; 323 if (m_caseDef.requirements & FEATURE_SHADER_INT_64) 324 extStream << "#extension GL_EXT_shader_explicit_arithmetic_types_int64 : require\n"; 325 if (m_caseDef.requirements & FEATURE_SHADER_INT_16) 326 extStream << "#extension GL_EXT_shader_explicit_arithmetic_types_int16 : require\n"; 327 if (m_caseDef.requirements & FEATURE_SHADER_INT_8) 328 extStream << "#extension GL_EXT_shader_explicit_arithmetic_types_int8 : require\n"; 329 if (m_caseDef.requirements & FEATURE_SHADER_FLOAT_16) 330 extStream << "#extension GL_EXT_shader_explicit_arithmetic_types_float16 : require\n"; 331 const std::string extensions = extStream.str(); 332 333 // This makes glslang avoid the UniformAndStorage* capabilities. 334 const vk::ShaderBuildOptions buildOptions (programCollection.usedVulkanVersion, SPIRV_VERSION_1_3, 0u); 335 336 if (requiredStages & VK_SHADER_STAGE_VERTEX_BIT) 337 { 338 const bool useSpecConst = (m_stage == VK_SHADER_STAGE_VERTEX_BIT); 339 std::ostringstream src; 340 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 341 << extensions 342 << "layout(location = 0) in highp vec4 position;\n" 343 << "\n" 344 << "out " << s_perVertexBlock << ";\n" 345 << "\n" 346 << (useSpecConst ? generateSpecConstantCode(m_caseDef.specConstants) : "") 347 << (useSpecConst ? generateSSBOCode(m_caseDef.ssboCode) : "") 348 << (useSpecConst ? m_caseDef.globalCode + "\n" : "") 349 << "void main (void)\n" 350 << "{\n" 351 << (useSpecConst ? m_caseDef.mainCode + "\n" : "") 352 << " gl_Position = position;\n" 353 << "}\n"; 354 355 programCollection.glslSources.add("vert") << glu::VertexSource(src.str()) << buildOptions; 356 } 357 358 if (requiredStages & VK_SHADER_STAGE_FRAGMENT_BIT) 359 { 360 const bool useSpecConst = (m_stage == VK_SHADER_STAGE_FRAGMENT_BIT); 361 std::ostringstream src; 362 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 363 << extensions 364 << "layout(location = 0) out highp vec4 fragColor;\n" 365 << "\n" 366 << (useSpecConst ? generateSpecConstantCode(m_caseDef.specConstants) : "") 367 << (useSpecConst ? generateSSBOCode(m_caseDef.ssboCode) : "") 368 << (useSpecConst ? m_caseDef.globalCode + "\n" : "") 369 << "void main (void)\n" 370 << "{\n" 371 << (useSpecConst ? m_caseDef.mainCode + "\n" : "") 372 << " fragColor = vec4(1.0, 1.0, 0.0, 1.0);\n" 373 << "}\n"; 374 375 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str()) << buildOptions; 376 } 377 378 if (requiredStages & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) 379 { 380 const bool useSpecConst = (m_stage == VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT); 381 std::ostringstream src; 382 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 383 << extensions 384 << "layout(vertices = 3) out;\n" 385 << "\n" 386 << "in " << s_perVertexBlock << " gl_in[gl_MaxPatchVertices];\n" 387 << "\n" 388 << "out " << s_perVertexBlock << " gl_out[];\n" 389 << "\n" 390 << (useSpecConst ? generateSpecConstantCode(m_caseDef.specConstants) : "") 391 << (useSpecConst ? generateSSBOCode(m_caseDef.ssboCode) : "") 392 << (useSpecConst ? m_caseDef.globalCode + "\n" : "") 393 << "void main (void)\n" 394 << "{\n" 395 << (useSpecConst ? m_caseDef.mainCode + "\n" : "") 396 << " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n" 397 << " if (gl_InvocationID == 0)\n" 398 << " {\n" 399 << " gl_TessLevelInner[0] = 3;\n" 400 << " gl_TessLevelOuter[0] = 2;\n" 401 << " gl_TessLevelOuter[1] = 2;\n" 402 << " gl_TessLevelOuter[2] = 2;\n" 403 << " }\n" 404 << "}\n"; 405 406 programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str()) << buildOptions; 407 } 408 409 if (requiredStages & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) 410 { 411 const bool useSpecConst = (m_stage == VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT); 412 std::ostringstream src; 413 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 414 << extensions 415 << "layout(triangles, equal_spacing, ccw) in;\n" 416 << "\n" 417 << "in " << s_perVertexBlock << " gl_in[gl_MaxPatchVertices];\n" 418 << "\n" 419 << "out " << s_perVertexBlock << ";\n" 420 << "\n" 421 << (useSpecConst ? generateSpecConstantCode(m_caseDef.specConstants) : "") 422 << (useSpecConst ? generateSSBOCode(m_caseDef.ssboCode) : "") 423 << (useSpecConst ? m_caseDef.globalCode + "\n" : "") 424 << "void main (void)\n" 425 << "{\n" 426 << (useSpecConst ? m_caseDef.mainCode + "\n" : "") 427 << " vec3 p0 = gl_TessCoord.x * gl_in[0].gl_Position.xyz;\n" 428 << " vec3 p1 = gl_TessCoord.y * gl_in[1].gl_Position.xyz;\n" 429 << " vec3 p2 = gl_TessCoord.z * gl_in[2].gl_Position.xyz;\n" 430 << " gl_Position = vec4(p0 + p1 + p2, 1.0);\n" 431 << "}\n"; 432 433 programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str()) << buildOptions; 434 } 435 436 if (requiredStages & VK_SHADER_STAGE_GEOMETRY_BIT) 437 { 438 const bool useSpecConst = (m_stage == VK_SHADER_STAGE_GEOMETRY_BIT); 439 std::ostringstream src; 440 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 441 << extensions 442 << "layout(triangles) in;\n" 443 << "layout(triangle_strip, max_vertices = 3) out;\n" 444 << "\n" 445 << "in " << s_perVertexBlock << " gl_in[];\n" 446 << "\n" 447 << "out " << s_perVertexBlock << ";\n" 448 << "\n" 449 << (useSpecConst ? generateSpecConstantCode(m_caseDef.specConstants) : "") 450 << (useSpecConst ? generateSSBOCode(m_caseDef.ssboCode) : "") 451 << (useSpecConst ? m_caseDef.globalCode + "\n" : "") 452 << "void main (void)\n" 453 << "{\n" 454 << (useSpecConst ? m_caseDef.mainCode + "\n" : "") 455 << " gl_Position = gl_in[0].gl_Position;\n" 456 << " EmitVertex();\n" 457 << "\n" 458 << " gl_Position = gl_in[1].gl_Position;\n" 459 << " EmitVertex();\n" 460 << "\n" 461 << " gl_Position = gl_in[2].gl_Position;\n" 462 << " EmitVertex();\n" 463 << "\n" 464 << " EndPrimitive();\n" 465 << "}\n"; 466 467 programCollection.glslSources.add("geom") << glu::GeometrySource(src.str()) << buildOptions; 468 } 469 470 if (requiredStages & VK_SHADER_STAGE_COMPUTE_BIT) 471 { 472 std::ostringstream src; 473 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 474 << extensions 475 // Don't define work group size, use the default or specialization constants 476 << "\n" 477 << generateSpecConstantCode(m_caseDef.specConstants) 478 << generateSSBOCode(m_caseDef.ssboCode) 479 << m_caseDef.globalCode + "\n" 480 << "void main (void)\n" 481 << "{\n" 482 << m_caseDef.mainCode 483 << "}\n"; 484 485 programCollection.glslSources.add("comp") << glu::ComputeSource(src.str()) << buildOptions; 486 } 487} 488 489class ComputeTestInstance : public TestInstance 490{ 491public: 492 ComputeTestInstance (Context& context, 493 PipelineConstructionType pipelineConstructionType, 494 const VkDeviceSize ssboSize, 495 const std::vector<SpecConstant>& specConstants, 496 const std::vector<OffsetValue>& expectedValues, 497 bool packData); 498 499 tcu::TestStatus iterate (void); 500 501private: 502 const PipelineConstructionType m_pipelineConstructionType; 503 const VkDeviceSize m_ssboSize; 504 const std::vector<SpecConstant> m_specConstants; 505 const std::vector<OffsetValue> m_expectedValues; 506 const bool m_packData; 507}; 508 509ComputeTestInstance::ComputeTestInstance (Context& context, 510 PipelineConstructionType pipelineConstructionType, 511 const VkDeviceSize ssboSize, 512 const std::vector<SpecConstant>& specConstants, 513 const std::vector<OffsetValue>& expectedValues, 514 bool packData) 515 : TestInstance (context) 516 , m_pipelineConstructionType (pipelineConstructionType) 517 , m_ssboSize (ssboSize) 518 , m_specConstants (specConstants) 519 , m_expectedValues (expectedValues) 520 , m_packData (packData) 521{ 522} 523 524tcu::TestStatus ComputeTestInstance::iterate (void) 525{ 526 const DeviceInterface& vk = m_context.getDeviceInterface(); 527 const VkDevice device = m_context.getDevice(); 528 const VkQueue queue = m_context.getUniversalQueue(); 529 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); 530 Allocator& allocator = m_context.getDefaultAllocator(); 531 532 // Descriptors 533 534 const BufferWithMemory resultBuffer(vk, device, allocator, makeBufferCreateInfo(m_ssboSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), MemoryRequirement::HostVisible); 535 536 const Unique<VkDescriptorSetLayout> descriptorSetLayout(DescriptorSetLayoutBuilder() 537 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT) 538 .build(vk, device)); 539 540 const Unique<VkDescriptorPool> descriptorPool(DescriptorPoolBuilder() 541 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER) 542 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u)); 543 544 const Unique<VkDescriptorSet> descriptorSet (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout)); 545 const VkDescriptorBufferInfo descriptorBufferInfo = makeDescriptorBufferInfo(resultBuffer.get(), 0ull, m_ssboSize); 546 547 DescriptorSetUpdateBuilder() 548 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorBufferInfo) 549 .update(vk, device); 550 551 // Specialization 552 553 const Specialization specialization (m_specConstants, m_packData); 554 const VkSpecializationInfo* pSpecInfo = specialization.getSpecializationInfo(); 555 556 // Pipeline 557 558 const PipelineLayoutWrapper pipelineLayout (m_pipelineConstructionType, vk, device, *descriptorSetLayout); 559 ComputePipelineWrapper pipeline (vk, device, graphicsToComputeConstructionType(m_pipelineConstructionType), m_context.getBinaryCollection().get("comp")); 560 pipeline.setDescriptorSetLayout(*descriptorSetLayout); 561 if (pSpecInfo) 562 pipeline.setSpecializationInfo(*pSpecInfo); 563 pipeline.buildPipeline(); 564 const Unique<VkCommandPool> cmdPool (createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex)); 565 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer (vk, device, *cmdPool)); 566 567 beginCommandBuffer(vk, *cmdBuffer); 568 569 pipeline.bind(*cmdBuffer); 570 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL); 571 572 vk.cmdDispatch(*cmdBuffer, 1u, 1u, 1u); 573 574 { 575 const VkBufferMemoryBarrier shaderWriteBarrier = makeBufferMemoryBarrier( 576 VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *resultBuffer, 0ull, m_ssboSize); 577 578 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 579 0u, DE_NULL, 1u, &shaderWriteBarrier, 0u, DE_NULL); 580 } 581 582 endCommandBuffer(vk, *cmdBuffer); 583 submitCommandsAndWait(vk, device, queue, *cmdBuffer); 584 585 // Verify results 586 587 const Allocation& resultAlloc = resultBuffer.getAllocation(); 588 invalidateAlloc(vk, device, resultAlloc); 589 590 if (verifyValues(m_context.getTestContext().getLog(), resultAlloc.getHostPtr(), m_expectedValues)) 591 return tcu::TestStatus::pass("Success"); 592 else 593 return tcu::TestStatus::fail("Values did not match"); 594} 595 596class GraphicsTestInstance : public TestInstance 597{ 598public: 599 GraphicsTestInstance (Context& context, 600 const PipelineConstructionType pipelineConstructionType, 601 const VkDeviceSize ssboSize, 602 const std::vector<SpecConstant>& specConstants, 603 const std::vector<OffsetValue>& expectedValues, 604 const VkShaderStageFlagBits stage, 605 bool packData); 606 607 tcu::TestStatus iterate (void); 608 609private: 610 const PipelineConstructionType m_pipelineConstructionType; 611 const VkDeviceSize m_ssboSize; 612 const std::vector<SpecConstant> m_specConstants; 613 const std::vector<OffsetValue> m_expectedValues; 614 const VkShaderStageFlagBits m_stage; 615 const bool m_packData; 616}; 617 618GraphicsTestInstance::GraphicsTestInstance (Context& context, 619 const PipelineConstructionType pipelineConstructionType, 620 const VkDeviceSize ssboSize, 621 const std::vector<SpecConstant>& specConstants, 622 const std::vector<OffsetValue>& expectedValues, 623 const VkShaderStageFlagBits stage, 624 bool packData) 625 : TestInstance (context) 626 , m_pipelineConstructionType (pipelineConstructionType) 627 , m_ssboSize (ssboSize) 628 , m_specConstants (specConstants) 629 , m_expectedValues (expectedValues) 630 , m_stage (stage) 631 , m_packData (packData) 632{ 633} 634 635tcu::TestStatus GraphicsTestInstance::iterate (void) 636{ 637 const InstanceInterface& vki = m_context.getInstanceInterface(); 638 const DeviceInterface& vk = m_context.getDeviceInterface(); 639 const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice(); 640 const VkDevice device = m_context.getDevice(); 641 const VkQueue queue = m_context.getUniversalQueue(); 642 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); 643 Allocator& allocator = m_context.getDefaultAllocator(); 644 645 // Color attachment 646 647 const tcu::IVec2 renderSize = tcu::IVec2(32, 32); 648 const VkFormat imageFormat = VK_FORMAT_R8G8B8A8_UNORM; 649 const ImageWithMemory colorImage (vk, device, allocator, makeImageCreateInfo(renderSize, imageFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT), MemoryRequirement::Any); 650 const Unique<VkImageView> colorImageView(makeImageView(vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, imageFormat, makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u))); 651 652 // Vertex buffer 653 654 const deUint32 numVertices = 3; 655 const VkDeviceSize vertexBufferSizeBytes = sizeof(tcu::Vec4) * numVertices; 656 const BufferWithMemory vertexBuffer (vk, device, allocator, makeBufferCreateInfo(vertexBufferSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), MemoryRequirement::HostVisible); 657 658 { 659 const Allocation& alloc = vertexBuffer.getAllocation(); 660 tcu::Vec4* pVertices = reinterpret_cast<tcu::Vec4*>(alloc.getHostPtr()); 661 662 pVertices[0] = tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f); 663 pVertices[1] = tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f); 664 pVertices[2] = tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f); 665 666 flushAlloc(vk, device, alloc); 667 // No barrier needed, flushed memory is automatically visible 668 } 669 670 // Descriptors 671 672 const BufferWithMemory resultBuffer(vk, device, allocator, makeBufferCreateInfo(m_ssboSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), MemoryRequirement::HostVisible); 673 674 const Unique<VkDescriptorSetLayout> descriptorSetLayout(DescriptorSetLayoutBuilder() 675 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_ALL_GRAPHICS) 676 .build(vk, device)); 677 678 const Unique<VkDescriptorPool> descriptorPool(DescriptorPoolBuilder() 679 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER) 680 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u)); 681 682 const Unique<VkDescriptorSet> descriptorSet (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout)); 683 const VkDescriptorBufferInfo descriptorBufferInfo = makeDescriptorBufferInfo(resultBuffer.get(), 0ull, m_ssboSize); 684 685 DescriptorSetUpdateBuilder() 686 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorBufferInfo) 687 .update(vk, device); 688 689 // Specialization 690 691 const Specialization specialization (m_specConstants, m_packData); 692 const VkSpecializationInfo* pSpecInfo = specialization.getSpecializationInfo(); 693 694 // Pipeline 695 696 RenderPassWrapper renderPass (m_pipelineConstructionType, vk, device, imageFormat); 697 renderPass.createFramebuffer(vk, device, colorImage.get(), colorImageView.get(), static_cast<deUint32>(renderSize.x()), static_cast<deUint32>(renderSize.y())); 698 const PipelineLayoutWrapper pipelineLayout (m_pipelineConstructionType, vk, device, *descriptorSetLayout); 699 const Unique<VkCommandPool> cmdPool (createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex)); 700 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer (vk, device, *cmdPool)); 701 702 vk::BinaryCollection& binaryCollection(m_context.getBinaryCollection()); 703 VkPrimitiveTopology topology (VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST); 704 const std::vector<VkViewport> viewport { makeViewport(renderSize) }; 705 const std::vector<VkRect2D> scissor { makeRect2D(renderSize) }; 706 707 ShaderWrapper vertShaderModule = ShaderWrapper(vk, device, binaryCollection.get("vert"), 0u); 708 ShaderWrapper tescShaderModule; 709 ShaderWrapper teseShaderModule; 710 ShaderWrapper geomShaderModule; 711 ShaderWrapper fragShaderModule = ShaderWrapper(vk, device, binaryCollection.get("frag"), 0u); 712 713 if ((m_stage == VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) || (m_stage == VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)) 714 { 715 tescShaderModule = ShaderWrapper(vk, device, binaryCollection.get("tesc"), 0u); 716 teseShaderModule = ShaderWrapper(vk, device, binaryCollection.get("tese"), 0u); 717 topology = VK_PRIMITIVE_TOPOLOGY_PATCH_LIST; 718 } 719 if (m_stage == VK_SHADER_STAGE_GEOMETRY_BIT) 720 geomShaderModule = ShaderWrapper(vk, device, binaryCollection.get("geom"), 0u); 721 722 GraphicsPipelineWrapper graphicsPipeline(vki, vk, physicalDevice, device, m_context.getDeviceExtensions(), m_pipelineConstructionType); 723 graphicsPipeline.setDefaultRasterizationState() 724 .setDefaultDepthStencilState() 725 .setDefaultMultisampleState() 726 .setDefaultColorBlendState() 727 .setDefaultTopology(topology) 728 .setupVertexInputState() 729 .setupPreRasterizationShaderState(viewport, 730 scissor, 731 pipelineLayout, 732 *renderPass, 733 0u, 734 vertShaderModule, 735 0u, 736 tescShaderModule, 737 teseShaderModule, 738 geomShaderModule, 739 pSpecInfo) 740 .setupFragmentShaderState(pipelineLayout, *renderPass, 0u, fragShaderModule, DE_NULL, DE_NULL, pSpecInfo) 741 .setupFragmentOutputState(*renderPass) 742 .setMonolithicPipelineLayout(pipelineLayout) 743 .buildPipeline(); 744 745 // Draw commands 746 747 const VkRect2D renderArea = makeRect2D(renderSize); 748 const tcu::Vec4 clearColor (0.0f, 0.0f, 0.0f, 1.0f); 749 const VkDeviceSize vertexBufferOffset = 0ull; 750 751 beginCommandBuffer(vk, *cmdBuffer); 752 753 { 754 const VkImageSubresourceRange imageFullSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u); 755 const VkImageMemoryBarrier barrierColorAttachmentSetInitialLayout = makeImageMemoryBarrier( 756 0u, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, 757 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 758 *colorImage, imageFullSubresourceRange); 759 760 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 761 0u, DE_NULL, 0u, DE_NULL, 1u, &barrierColorAttachmentSetInitialLayout); 762 } 763 764 renderPass.begin(vk, *cmdBuffer, renderArea, clearColor); 765 766 graphicsPipeline.bind(*cmdBuffer); 767 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL); 768 vk.cmdBindVertexBuffers (*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset); 769 770 vk.cmdDraw(*cmdBuffer, numVertices, 1u, 0u, 0u); 771 renderPass.end(vk, *cmdBuffer); 772 773 { 774 const VkBufferMemoryBarrier shaderWriteBarrier = makeBufferMemoryBarrier( 775 VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *resultBuffer, 0ull, m_ssboSize); 776 777 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 778 0u, DE_NULL, 1u, &shaderWriteBarrier, 0u, DE_NULL); 779 } 780 781 endCommandBuffer(vk, *cmdBuffer); 782 submitCommandsAndWait(vk, device, queue, *cmdBuffer); 783 784 // Verify results 785 786 const Allocation& resultAlloc = resultBuffer.getAllocation(); 787 invalidateAlloc(vk, device, resultAlloc); 788 789 if (verifyValues(m_context.getTestContext().getLog(), resultAlloc.getHostPtr(), m_expectedValues)) 790 return tcu::TestStatus::pass("Success"); 791 else 792 return tcu::TestStatus::fail("Values did not match"); 793} 794 795FeatureFlags getShaderStageRequirements (const VkShaderStageFlags stageFlags) 796{ 797 FeatureFlags features = (FeatureFlags)0; 798 799 if (((stageFlags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0) || ((stageFlags & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0)) 800 features |= FEATURE_TESSELLATION_SHADER; 801 802 if ((stageFlags & VK_SHADER_STAGE_GEOMETRY_BIT) != 0) 803 features |= FEATURE_GEOMETRY_SHADER; 804 805 // All tests use SSBO writes to read back results. 806 if ((stageFlags & VK_SHADER_STAGE_ALL_GRAPHICS) != 0) 807 { 808 if ((stageFlags & VK_SHADER_STAGE_FRAGMENT_BIT) != 0) 809 features |= FEATURE_FRAGMENT_STORES_AND_ATOMICS; 810 else 811 features |= FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS; 812 } 813 814 return features; 815} 816 817void SpecConstantTest::checkSupport (Context& context) const 818{ 819 requireFeatures(context, m_caseDef.requirements | getShaderStageRequirements(m_stage)); 820 checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_pipelineConstructionType); 821} 822 823TestInstance* SpecConstantTest::createInstance (Context& context) const 824{ 825 if (m_stage & VK_SHADER_STAGE_COMPUTE_BIT) 826 return new ComputeTestInstance(context, m_pipelineConstructionType, m_caseDef.ssboSize, m_caseDef.specConstants, m_caseDef.expectedValues, m_caseDef.packData); 827 else 828 return new GraphicsTestInstance(context, m_pipelineConstructionType, m_caseDef.ssboSize, m_caseDef.specConstants, m_caseDef.expectedValues, m_stage, m_caseDef.packData); 829} 830 831//! Declare specialization constants but use them with default values. 832tcu::TestCaseGroup* createDefaultValueTests (tcu::TestContext& testCtx, const PipelineConstructionType pipelineType, const VkShaderStageFlagBits shaderStage) 833{ 834 // use default constant value 835 de::MovePtr<tcu::TestCaseGroup> testGroup (new tcu::TestCaseGroup(testCtx, "default_value")); 836 837 CaseDefinition defs[] = 838 { 839 { 840 "bool", 841 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const bool sc0 = true;"), 842 SpecConstant(2u, "layout(constant_id = ${ID}) const bool sc1 = false;")), 843 8, 844 " bool r0;\n" 845 " bool r1;\n", 846 "", 847 " sb_out.r0 = sc0;\n" 848 " sb_out.r1 = sc1;\n", 849 makeVector(OffsetValue(4, 0, makeValueBool32(true)), 850 OffsetValue(4, 4, makeValueBool32(false))), 851 (FeatureFlags)0, 852 false, 853 }, 854 { 855 "int8", 856 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const int8_t sc0 = int8_t(1);"), 857 SpecConstant(2u, "layout(constant_id = ${ID}) const int8_t sc1 = int8_t(-2);")), 858 2, 859 " int8_t r0;\n" 860 " int8_t r1;\n", 861 "", 862 " int8_t aux = sc0 + sc1;\n" 863 " sb_out.r0 = sc0;\n" 864 " sb_out.r1 = sc1;\n", 865 makeVector(OffsetValue(1, 0, makeValueInt8(1)), 866 OffsetValue(1, 1, makeValueInt8(-2))), 867 FEATURE_SHADER_INT_8, 868 false, 869 }, 870 { 871 "uint8", 872 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const uint8_t sc0 = int8_t(15);"), 873 SpecConstant(2u, "layout(constant_id = ${ID}) const uint8_t sc1 = int8_t(43);")), 874 2, 875 " uint8_t r0;\n" 876 " uint8_t r1;\n", 877 "", 878 " uint8_t aux = sc0 + sc1;\n" 879 " sb_out.r0 = sc0;\n" 880 " sb_out.r1 = sc1;\n", 881 makeVector(OffsetValue(1, 0, makeValueUint8(15)), 882 OffsetValue(1, 1, makeValueUint8(43))), 883 FEATURE_SHADER_INT_8, 884 false, 885 }, 886 { 887 "int16", 888 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const int16_t sc0 = 20000s;", 2, makeValueInt16(32000)), 889 SpecConstant(2u, "layout(constant_id = ${ID}) const int16_t sc1 = -20000s;")), 890 4, 891 " int16_t r0;\n" 892 " int16_t r1;\n", 893 "", 894 " int16_t aux = sc0 + sc1;\n" 895 " sb_out.r0 = sc0;\n" 896 " sb_out.r1 = sc1;\n", 897 makeVector(OffsetValue(2, 0, makeValueInt16(32000)), 898 OffsetValue(2, 2, makeValueInt16(-20000))), 899 FEATURE_SHADER_INT_16, 900 false, 901 }, 902 { 903 "uint16", 904 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const uint16_t sc0 = 64000us;"), 905 SpecConstant(2u, "layout(constant_id = ${ID}) const uint16_t sc1 = 51829us;")), 906 4, 907 " uint16_t r0;\n" 908 " uint16_t r1;\n", 909 "", 910 " uint16_t aux = sc0 + sc1;\n" 911 " sb_out.r0 = sc0;\n" 912 " sb_out.r1 = sc1;\n", 913 makeVector(OffsetValue(2, 0, makeValueUint16(64000)), 914 OffsetValue(2, 2, makeValueUint16(51829))), 915 FEATURE_SHADER_INT_16, 916 false, 917 }, 918 { 919 "int", 920 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const int sc0 = -3;"), 921 SpecConstant(2u, "layout(constant_id = ${ID}) const int sc1 = 17;")), 922 8, 923 " int r0;\n" 924 " int r1;\n", 925 "", 926 " sb_out.r0 = sc0;\n" 927 " sb_out.r1 = sc1;\n", 928 makeVector(OffsetValue(4, 0, makeValueInt32(-3)), 929 OffsetValue(4, 4, makeValueInt32(17))), 930 (FeatureFlags)0, 931 false, 932 }, 933 { 934 "uint", 935 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const uint sc0 = 42u;")), 936 4, 937 " uint r0;\n", 938 "", 939 " sb_out.r0 = sc0;\n", 940 makeVector(OffsetValue(4, 0, makeValueUint32(42u))), 941 (FeatureFlags)0, 942 false, 943 }, 944 { 945 "int64", 946 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const int64_t sc0 = 9141386509785772560l;"), 947 SpecConstant(2u, "layout(constant_id = ${ID}) const int64_t sc1 = -9141386509785772560l;")), 948 16, 949 " int64_t r0;\n" 950 " int64_t r1;\n", 951 "", 952 " sb_out.r0 = sc0;\n" 953 " sb_out.r1 = sc1;\n", 954 makeVector(OffsetValue(8, 0, makeValueInt64(9141386509785772560ll)), 955 OffsetValue(8, 8, makeValueInt64(-9141386509785772560ll))), 956 FEATURE_SHADER_INT_64, 957 false, 958 }, 959 { 960 "uint64", 961 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const uint64_t sc0 = 18364758544493064720ul;"), 962 SpecConstant(2u, "layout(constant_id = ${ID}) const uint64_t sc1 = 17298946664678735070ul;")), 963 16, 964 " uint64_t r0;\n" 965 " uint64_t r1;\n", 966 "", 967 " sb_out.r0 = sc0;\n" 968 " sb_out.r1 = sc1;\n", 969 makeVector(OffsetValue(8, 0, makeValueUint64(18364758544493064720ull)), 970 OffsetValue(8, 8, makeValueUint64(17298946664678735070ull))), 971 FEATURE_SHADER_INT_64, 972 false, 973 }, 974 { 975 "float16", 976 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const float16_t sc0 = 7.5hf;"), 977 SpecConstant(2u, "layout(constant_id = ${ID}) const float16_t sc1 = 1.125hf;")), 978 4, 979 " float16_t r0;\n" 980 " float16_t r1;\n", 981 "", 982 " float16_t aux = sc0 + sc1;\n" 983 " sb_out.r0 = sc0;\n" 984 " sb_out.r1 = sc1;\n", 985 makeVector(OffsetValue(2, 0, makeValueFloat16(tcu::Float16(7.5))), 986 OffsetValue(2, 2, makeValueFloat16(tcu::Float16(1.125)))), 987 FEATURE_SHADER_FLOAT_16, 988 false, 989 }, 990 { 991 "float", 992 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const float sc0 = 7.5;")), 993 4, 994 " float r0;\n", 995 "", 996 " sb_out.r0 = sc0;\n", 997 makeVector(OffsetValue(4, 0, makeValueFloat32(7.5f))), 998 (FeatureFlags)0, 999 false, 1000 }, 1001 { 1002 "double", 1003 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const double sc0 = 2.75LF;")), 1004 8, 1005 " double r0;\n", 1006 "", 1007 " sb_out.r0 = sc0;\n", 1008 makeVector(OffsetValue(8, 0, makeValueFloat64(2.75))), 1009 FEATURE_SHADER_FLOAT_64, 1010 false, 1011 }, 1012 }; 1013 1014 for (int i = 0; i < 2; ++i) 1015 { 1016 const bool packData = (i > 0); 1017 for (int defNdx = 0; defNdx < DE_LENGTH_OF_ARRAY(defs); ++defNdx) 1018 { 1019 auto& def = defs[defNdx]; 1020 def.packData = packData; 1021 if (packData) 1022 def.name += "_packed"; 1023 testGroup->addChild(new SpecConstantTest(testCtx, pipelineType, shaderStage, def)); 1024 } 1025 } 1026 1027 return testGroup.release(); 1028} 1029 1030//! Declare specialization constants and specify their values through API. 1031tcu::TestCaseGroup* createBasicSpecializationTests (tcu::TestContext& testCtx, const PipelineConstructionType pipelineType, const VkShaderStageFlagBits shaderStage) 1032{ 1033 de::MovePtr<tcu::TestCaseGroup> testGroup (new tcu::TestCaseGroup(testCtx, "basic", "specialize a constant")); 1034 1035 CaseDefinition defs[] = 1036 { 1037 { 1038 "bool", 1039 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const bool sc0 = true;", 4, makeValueBool32(true)), 1040 SpecConstant(2u, "layout(constant_id = ${ID}) const bool sc1 = false;", 4, makeValueBool32(false)), 1041 SpecConstant(3u, "layout(constant_id = ${ID}) const bool sc2 = true;", 4, makeValueBool32(false)), 1042 SpecConstant(4u, "layout(constant_id = ${ID}) const bool sc3 = false;", 4, makeValueBool32(true))), 1043 16, 1044 " bool r0;\n" 1045 " bool r1;\n" 1046 " bool r2;\n" 1047 " bool r3;\n", 1048 "", 1049 " sb_out.r0 = sc0;\n" 1050 " sb_out.r1 = sc1;\n" 1051 " sb_out.r2 = sc2;\n" 1052 " sb_out.r3 = sc3;\n", 1053 makeVector(OffsetValue(4, 0, makeValueBool32(true)), 1054 OffsetValue(4, 4, makeValueBool32(false)), 1055 OffsetValue(4, 8, makeValueBool32(false)), 1056 OffsetValue(4, 12, makeValueBool32(true))), 1057 (FeatureFlags)0, 1058 false, 1059 }, 1060 { 1061 "int8", 1062 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const int8_t sc0 = int8_t(1);", 1, makeValueInt8(127)), 1063 SpecConstant(2u, "layout(constant_id = ${ID}) const int8_t sc1 = int8_t(-2);")), 1064 2, 1065 " int8_t r0;\n" 1066 " int8_t r1;\n", 1067 "", 1068 " int8_t aux = sc0 + sc1;\n" 1069 " sb_out.r0 = sc0;\n" 1070 " sb_out.r1 = sc1;\n", 1071 makeVector(OffsetValue(1, 0, makeValueInt8(127)), 1072 OffsetValue(1, 1, makeValueInt8(-2))), 1073 FEATURE_SHADER_INT_8, 1074 false, 1075 }, 1076 { 1077 "int8_2", 1078 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const int8_t sc0 = int8_t(123);", 1, makeValueInt8(65)), 1079 SpecConstant(2u, "layout(constant_id = ${ID}) const int8_t sc1 = int8_t(-33);", 1, makeValueInt8(-128))), 1080 2, 1081 " int8_t r0;\n" 1082 " int8_t r1;\n", 1083 "", 1084 " int8_t aux = sc0 + sc1;\n" 1085 " sb_out.r0 = sc0;\n" 1086 " sb_out.r1 = sc1;\n", 1087 makeVector(OffsetValue(1, 0, makeValueInt8(65)), 1088 OffsetValue(1, 1, makeValueInt8(-128))), 1089 FEATURE_SHADER_INT_8, 1090 false, 1091 }, 1092 { 1093 "uint8", 1094 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const uint8_t sc0 = int8_t(15);", 1, makeValueUint8(254)), 1095 SpecConstant(2u, "layout(constant_id = ${ID}) const uint8_t sc1 = int8_t(43);")), 1096 2, 1097 " uint8_t r0;\n" 1098 " uint8_t r1;\n", 1099 "", 1100 " uint8_t aux = sc0 + sc1;\n" 1101 " sb_out.r0 = sc0;\n" 1102 " sb_out.r1 = sc1;\n", 1103 makeVector(OffsetValue(1, 0, makeValueUint8(254)), 1104 OffsetValue(1, 1, makeValueUint8(43))), 1105 FEATURE_SHADER_INT_8, 1106 false, 1107 }, 1108 { 1109 "uint8_2", 1110 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const uint8_t sc0 = int8_t(99);", 1, makeValueUint8(254)), 1111 SpecConstant(2u, "layout(constant_id = ${ID}) const uint8_t sc1 = int8_t(81);", 1, makeValueUint8(255))), 1112 2, 1113 " uint8_t r0;\n" 1114 " uint8_t r1;\n", 1115 "", 1116 " uint8_t aux = sc0 + sc1;\n" 1117 " sb_out.r0 = sc0;\n" 1118 " sb_out.r1 = sc1;\n", 1119 makeVector(OffsetValue(1, 0, makeValueUint8(254)), 1120 OffsetValue(1, 1, makeValueUint8(255))), 1121 FEATURE_SHADER_INT_8, 1122 false, 1123 }, 1124 { 1125 "int16", 1126 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const int16_t sc0 = 20000s;", 2, makeValueInt16(32000)), 1127 SpecConstant(2u, "layout(constant_id = ${ID}) const int16_t sc1 = -20000s;")), 1128 4, 1129 " int16_t r0;\n" 1130 " int16_t r1;\n", 1131 "", 1132 " int16_t aux = sc0 + sc1;\n" 1133 " sb_out.r0 = sc0;\n" 1134 " sb_out.r1 = sc1;\n", 1135 makeVector(OffsetValue(2, 0, makeValueInt16(32000)), 1136 OffsetValue(2, 2, makeValueInt16(-20000))), 1137 FEATURE_SHADER_INT_16, 1138 false, 1139 }, 1140 { 1141 "int16_2", 1142 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const int16_t sc0 = 20000s;", 2, makeValueInt16(32000)), 1143 SpecConstant(2u, "layout(constant_id = ${ID}) const int16_t sc1 = -20000s;", 2, makeValueInt16(-21000))), 1144 4, 1145 " int16_t r0;\n" 1146 " int16_t r1;\n", 1147 "", 1148 " int16_t aux = sc0 + sc1;\n" 1149 " sb_out.r0 = sc0;\n" 1150 " sb_out.r1 = sc1;\n", 1151 makeVector(OffsetValue(2, 0, makeValueInt16(32000)), 1152 OffsetValue(2, 2, makeValueInt16(-21000))), 1153 FEATURE_SHADER_INT_16, 1154 false, 1155 }, 1156 { 1157 "uint16", 1158 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const uint16_t sc0 = 64000us;", 2, makeValueUint16(65000)), 1159 SpecConstant(2u, "layout(constant_id = ${ID}) const uint16_t sc1 = 51829us;")), 1160 4, 1161 " uint16_t r0;\n" 1162 " uint16_t r1;\n", 1163 "", 1164 " uint16_t aux = sc0 + sc1;\n" 1165 " sb_out.r0 = sc0;\n" 1166 " sb_out.r1 = sc1;\n", 1167 makeVector(OffsetValue(2, 0, makeValueUint16(65000)), 1168 OffsetValue(2, 2, makeValueUint16(51829))), 1169 FEATURE_SHADER_INT_16, 1170 false, 1171 }, 1172 { 1173 "uint16_2", 1174 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const uint16_t sc0 = 64000us;", 2, makeValueUint16(65000)), 1175 SpecConstant(2u, "layout(constant_id = ${ID}) const uint16_t sc1 = 51829us;", 2, makeValueUint16(63000))), 1176 4, 1177 " uint16_t r0;\n" 1178 " uint16_t r1;\n", 1179 "", 1180 " uint16_t aux = sc0 + sc1;\n" 1181 " sb_out.r0 = sc0;\n" 1182 " sb_out.r1 = sc1;\n", 1183 makeVector(OffsetValue(2, 0, makeValueUint16(65000)), 1184 OffsetValue(2, 2, makeValueUint16(63000))), 1185 FEATURE_SHADER_INT_16, 1186 false, 1187 }, 1188 { 1189 "int", 1190 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const int sc0 = -3;", 4, makeValueInt32(33)), 1191 SpecConstant(2u, "layout(constant_id = ${ID}) const int sc1 = 91;"), 1192 SpecConstant(3u, "layout(constant_id = ${ID}) const int sc2 = 17;", 4, makeValueInt32(-15))), 1193 12, 1194 " int r0;\n" 1195 " int r1;\n" 1196 " int r2;\n", 1197 "", 1198 " sb_out.r0 = sc0;\n" 1199 " sb_out.r1 = sc1;\n" 1200 " sb_out.r2 = sc2;\n", 1201 makeVector(OffsetValue(4, 0, makeValueInt32(33)), 1202 OffsetValue(4, 4, makeValueInt32(91)), 1203 OffsetValue(4, 8, makeValueInt32(-15))), 1204 (FeatureFlags)0, 1205 false, 1206 }, 1207 { 1208 "uint", 1209 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const uint sc0 = 42u;", 4, makeValueUint32(97u)), 1210 SpecConstant(2u, "layout(constant_id = ${ID}) const uint sc1 = 7u;")), 1211 8, 1212 " uint r0;\n" 1213 " uint r1;\n", 1214 "", 1215 " sb_out.r0 = sc0;\n" 1216 " sb_out.r1 = sc1;\n", 1217 makeVector(OffsetValue(4, 0, makeValueUint32(97u)), 1218 OffsetValue(4, 4, makeValueUint32(7u))), 1219 (FeatureFlags)0, 1220 false, 1221 }, 1222 { 1223 "uint_2", 1224 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const uint sc0 = 305419896u;", 4, makeValueUint32(1985229328u)), 1225 SpecConstant(2u, "layout(constant_id = ${ID}) const uint sc1 = 591751049u;"), 1226 SpecConstant(3u, "layout(constant_id = ${ID}) const uint sc2 = 878082202u;", 4, makeValueUint32(1698898186u))), 1227 12, 1228 " uint r0;\n" 1229 " uint r1;\n" 1230 " uint r2;\n", 1231 "", 1232 " sb_out.r0 = sc0;\n" 1233 " sb_out.r1 = sc1;\n" 1234 " sb_out.r2 = sc2;\n", 1235 makeVector(OffsetValue(4, 0, makeValueUint32(1985229328u)), 1236 OffsetValue(4, 4, makeValueUint32(591751049u)), 1237 OffsetValue(4, 8, makeValueUint32(1698898186u))), 1238 (FeatureFlags)0, 1239 false, 1240 }, 1241 { 1242 "int64", 1243 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const int64_t sc0 = 9141386509785772560l;", 8, makeValueInt64(9137147825770275585ll)), 1244 SpecConstant(2u, "layout(constant_id = ${ID}) const int64_t sc1 = -9141386509785772560l;")), 1245 16, 1246 " int64_t r0;\n" 1247 " int64_t r1;\n", 1248 "", 1249 " sb_out.r0 = sc0;\n" 1250 " sb_out.r1 = sc1;\n", 1251 makeVector(OffsetValue(8, 0, makeValueInt64(9137147825770275585ll)), 1252 OffsetValue(8, 8, makeValueInt64(-9141386509785772560ll))), 1253 FEATURE_SHADER_INT_64, 1254 false, 1255 }, 1256 { 1257 "int64_2", 1258 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const int64_t sc0 = 9141386509785772560l;", 8, makeValueInt64(9137147825770275585ll)), 1259 SpecConstant(2u, "layout(constant_id = ${ID}) const int64_t sc1 = -9141386509785772560l;", 8, makeValueInt64(-9137164382869201665ll))), 1260 16, 1261 " int64_t r0;\n" 1262 " int64_t r1;\n", 1263 "", 1264 " sb_out.r0 = sc0;\n" 1265 " sb_out.r1 = sc1;\n", 1266 makeVector(OffsetValue(8, 0, makeValueInt64(9137147825770275585ll)), 1267 OffsetValue(8, 8, makeValueInt64(-9137164382869201665ll))), 1268 FEATURE_SHADER_INT_64, 1269 false, 1270 }, 1271 { 1272 "uint64", 1273 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const uint64_t sc0 = 18364758544493064720ul;", 8, makeValueUint64(17279655951921914625ull)), 1274 SpecConstant(2u, "layout(constant_id = ${ID}) const uint64_t sc1 = 17298946664678735070ul;")), 1275 16, 1276 " uint64_t r0;\n" 1277 " uint64_t r1;\n", 1278 "", 1279 " sb_out.r0 = sc0;\n" 1280 " sb_out.r1 = sc1;\n", 1281 makeVector(OffsetValue(8, 0, makeValueUint64(17279655951921914625ull)), 1282 OffsetValue(8, 8, makeValueUint64(17298946664678735070ull))), 1283 FEATURE_SHADER_INT_64, 1284 false, 1285 }, 1286 { 1287 "uint64_2", 1288 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const uint64_t sc0 = 18364758544493064720ul;", 8, makeValueUint64(17279655951921914625ull)), 1289 SpecConstant(2u, "layout(constant_id = ${ID}) const uint64_t sc1 = 17298946664678735070ul;", 8, makeValueUint64(17270123250533606145ull))), 1290 16, 1291 " uint64_t r0;\n" 1292 " uint64_t r1;\n", 1293 "", 1294 " sb_out.r0 = sc0;\n" 1295 " sb_out.r1 = sc1;\n", 1296 makeVector(OffsetValue(8, 0, makeValueUint64(17279655951921914625ull)), 1297 OffsetValue(8, 8, makeValueUint64(17270123250533606145ull))), 1298 FEATURE_SHADER_INT_64, 1299 false, 1300 }, 1301 // We create some floating point values below as unsigned integers to make sure all bytes are set to different values, avoiding special patterns and denormals. 1302 { 1303 "float16", 1304 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const float16_t sc0 = 7.5hf;", 2, makeValueFloat16(tcu::Float16(15.75))), 1305 SpecConstant(2u, "layout(constant_id = ${ID}) const float16_t sc1 = 1.125hf;")), 1306 4, 1307 " float16_t r0;\n" 1308 " float16_t r1;\n", 1309 "", 1310 " float16_t aux = sc0 + sc1;\n" 1311 " sb_out.r0 = sc0;\n" 1312 " sb_out.r1 = sc1;\n", 1313 makeVector(OffsetValue(2, 0, makeValueFloat16(tcu::Float16(15.75))), 1314 OffsetValue(2, 2, makeValueFloat16(tcu::Float16(1.125)))), 1315 FEATURE_SHADER_FLOAT_16, 1316 false, 1317 }, 1318 { 1319 "float16_2", 1320 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const float16_t sc0 = 7.5hf;", 2, makeValueUint16(0x0123u)), 1321 SpecConstant(2u, "layout(constant_id = ${ID}) const float16_t sc1 = 1.125hf;"), 1322 SpecConstant(3u, "layout(constant_id = ${ID}) const float16_t sc2 = 1.125hf;", 2, makeValueUint16(0xFEDCu))), 1323 6, 1324 " float16_t r0;\n" 1325 " float16_t r1;\n" 1326 " float16_t r2;\n", 1327 "", 1328 " float16_t aux = sc0 + sc1;\n" 1329 " sb_out.r0 = sc0;\n" 1330 " sb_out.r1 = sc1;\n" 1331 " sb_out.r2 = sc2;\n", 1332 makeVector(OffsetValue(2, 0, makeValueUint16(0x0123u)), 1333 OffsetValue(2, 2, makeValueFloat16(tcu::Float16(1.125))), 1334 OffsetValue(2, 4, makeValueUint16(0xFEDCu))), 1335 FEATURE_SHADER_FLOAT_16, 1336 false, 1337 }, 1338 { 1339 "float", 1340 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const float sc0 = 7.5;", 4, makeValueFloat32(15.75f)), 1341 SpecConstant(2u, "layout(constant_id = ${ID}) const float sc1 = 1.125;")), 1342 8, 1343 " float r0;\n" 1344 " float r1;\n", 1345 "", 1346 " sb_out.r0 = sc0;\n" 1347 " sb_out.r1 = sc1;\n", 1348 makeVector(OffsetValue(4, 0, makeValueFloat32(15.75f)), 1349 OffsetValue(4, 4, makeValueFloat32(1.125f))), 1350 (FeatureFlags)0, 1351 false, 1352 }, 1353 { 1354 "float_2", 1355 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const float sc0 = 7.5;", 4, makeValueUint32(0x01234567u)), 1356 SpecConstant(2u, "layout(constant_id = ${ID}) const float sc1 = 1.125;"), 1357 SpecConstant(3u, "layout(constant_id = ${ID}) const float sc2 = 1.125;", 4, makeValueUint32(0xfedcba98u))), 1358 12, 1359 " float r0;\n" 1360 " float r1;\n" 1361 " float r2;\n", 1362 "", 1363 " sb_out.r0 = sc0;\n" 1364 " sb_out.r1 = sc1;\n" 1365 " sb_out.r2 = sc2;\n", 1366 makeVector(OffsetValue(4, 0, makeValueUint32(0x01234567u)), 1367 OffsetValue(4, 4, makeValueFloat32(1.125f)), 1368 OffsetValue(4, 8, makeValueUint32(0xfedcba98u))), 1369 (FeatureFlags)0, 1370 false, 1371 }, 1372 { 1373 "double", 1374 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const double sc0 = 2.75LF;", 8, makeValueUint64(0xFEDCBA9876543210ull)), 1375 SpecConstant(2u, "layout(constant_id = ${ID}) const double sc1 = 9.25LF;")), 1376 16, 1377 " double r0;\n" 1378 " double r1;\n", 1379 "", 1380 " sb_out.r0 = sc0;\n" 1381 " sb_out.r1 = sc1;\n", 1382 makeVector(OffsetValue(8, 0, makeValueUint64(0xFEDCBA9876543210ull)), 1383 OffsetValue(8, 8, makeValueFloat64(9.25))), 1384 FEATURE_SHADER_FLOAT_64, 1385 false, 1386 }, 1387 { 1388 "double_2", 1389 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const double sc0 = 2.75LF;", 8, makeValueUint64(0xFEDCBA9876543210ull)), 1390 SpecConstant(2u, "layout(constant_id = ${ID}) const double sc1 = 9.25LF;", 8, makeValueUint64(0xEFCDAB8967452301ull))), 1391 16, 1392 " double r0;\n" 1393 " double r1;\n", 1394 "", 1395 " sb_out.r0 = sc0;\n" 1396 " sb_out.r1 = sc1;\n", 1397 makeVector(OffsetValue(8, 0, makeValueUint64(0xFEDCBA9876543210ull)), 1398 OffsetValue(8, 8, makeValueUint64(0xEFCDAB8967452301ull))), 1399 FEATURE_SHADER_FLOAT_64, 1400 false, 1401 }, 1402 { 1403 "mixed", 1404 makeVector( 1405 SpecConstant(1u, "layout(constant_id = ${ID}) const uint8_t sc0 = uint8_t (0);", 1, makeValueUint8(0x98)), 1406 SpecConstant(2u, "layout(constant_id = ${ID}) const uint16_t sc1 = uint16_t (0);", 2, makeValueUint16(0x9876)), 1407 SpecConstant(3u, "layout(constant_id = ${ID}) const uint sc2 = uint (0);", 4, makeValueUint32(0xba987654u)), 1408 SpecConstant(4u, "layout(constant_id = ${ID}) const uint64_t sc3 = uint64_t (0);", 8, makeValueUint64(0xfedcba9876543210ull))), 1409 8+4+2+1, 1410 " uint64_t r0;\n" 1411 " uint r1;\n" 1412 " uint16_t r2;\n" 1413 " uint8_t r3;\n", 1414 "", 1415 " uint64_t i0 = sc3;\n" 1416 " uint i1 = sc2;\n" 1417 " uint16_t i2 = sc1;\n" 1418 " uint8_t i3 = sc0;\n" 1419 " sb_out.r0 = i0;\n" 1420 " sb_out.r1 = i1;\n" 1421 " sb_out.r2 = i2;\n" 1422 " sb_out.r3 = i3;\n", 1423 makeVector( 1424 OffsetValue(8, 0, makeValueUint64(0xfedcba9876543210ull)), 1425 OffsetValue(4, 8, makeValueUint32(0xba987654u)), 1426 OffsetValue(2, 12, makeValueUint16(0x9876)), 1427 OffsetValue(1, 14, makeValueUint8(0x98))), 1428 (FEATURE_SHADER_INT_8 | FEATURE_SHADER_INT_16 | FEATURE_SHADER_INT_64), 1429 false, 1430 }, 1431 { 1432 "mixed_reversed", 1433 makeVector( 1434 SpecConstant(1u, "layout(constant_id = ${ID}) const uint64_t sc3 = uint64_t (0);", 8, makeValueUint64(0xfedcba9876543210ull)), 1435 SpecConstant(2u, "layout(constant_id = ${ID}) const uint sc2 = uint (0);", 4, makeValueUint32(0xba987654u)), 1436 SpecConstant(3u, "layout(constant_id = ${ID}) const uint16_t sc1 = uint16_t (0);", 2, makeValueUint16(0x9876)), 1437 SpecConstant(4u, "layout(constant_id = ${ID}) const uint8_t sc0 = uint8_t (0);", 1, makeValueUint8(0x98))), 1438 8+4+2+1, 1439 " uint64_t r0;\n" 1440 " uint r1;\n" 1441 " uint16_t r2;\n" 1442 " uint8_t r3;\n", 1443 "", 1444 " uint64_t i0 = sc3;\n" 1445 " uint i1 = sc2;\n" 1446 " uint16_t i2 = sc1;\n" 1447 " uint8_t i3 = sc0;\n" 1448 " sb_out.r0 = i0;\n" 1449 " sb_out.r1 = i1;\n" 1450 " sb_out.r2 = i2;\n" 1451 " sb_out.r3 = i3;\n", 1452 makeVector( 1453 OffsetValue(8, 0, makeValueUint64(0xfedcba9876543210ull)), 1454 OffsetValue(4, 8, makeValueUint32(0xba987654u)), 1455 OffsetValue(2, 12, makeValueUint16(0x9876)), 1456 OffsetValue(1, 14, makeValueUint8(0x98))), 1457 (FEATURE_SHADER_INT_8 | FEATURE_SHADER_INT_16 | FEATURE_SHADER_INT_64), 1458 false, 1459 }, 1460 }; 1461 1462 for (int i = 0; i < 2; ++i) 1463 { 1464 const bool packData = (i > 0); 1465 for (int defNdx = 0; defNdx < DE_LENGTH_OF_ARRAY(defs); ++defNdx) 1466 { 1467 auto& def = defs[defNdx]; 1468 def.packData = packData; 1469 if (packData) 1470 def.name += "_packed"; 1471 testGroup->addChild(new SpecConstantTest(testCtx, pipelineType, shaderStage, def)); 1472 } 1473 } 1474 1475 CaseDefinition defsUnusedCases[] = 1476 { 1477 { 1478 "unused_single", 1479 makeVector(SpecConstant(0u, "", 0u, GenericValue(), true)), 1480 4, 1481 " int r0;\n", 1482 "", 1483 " sb_out.r0 = 77;\n", 1484 makeVector(OffsetValue(4u, 0u, makeValueInt32(77))), 1485 (FeatureFlags)0, 1486 false, 1487 }, 1488 { 1489 "unused_single_packed", 1490 makeVector(SpecConstant(0u, "", 0u, GenericValue(), true), 1491 SpecConstant(1u, "layout(constant_id = ${ID}) const int sc1 = 0;", 4u, makeValueInt32(100))), 1492 4, 1493 " int r1;\n", 1494 "", 1495 " sb_out.r1 = sc1;\n", 1496 makeVector(OffsetValue(4u, 0u, makeValueInt32(100))), 1497 (FeatureFlags)0, 1498 true, 1499 }, 1500 { 1501 "unused_multiple", 1502 makeVector(SpecConstant( 7u, "layout(constant_id = ${ID}) const int sc0 = 0;", 4u, makeValueInt32(-999)), 1503 SpecConstant( 1u, "", 0u, GenericValue(), true), 1504 SpecConstant(17u, "layout(constant_id = ${ID}) const int sc1 = 0;", 4u, makeValueInt32( 999)), 1505 SpecConstant( 3u, "", 0u, GenericValue(), true)), 1506 8, 1507 " int r0;\n" 1508 " int r1;\n", 1509 "", 1510 " sb_out.r0 = sc0;\n" 1511 " sb_out.r1 = sc1;\n", 1512 makeVector(OffsetValue(4, 0, makeValueInt32(-999)), 1513 OffsetValue(4, 4, makeValueInt32( 999))), 1514 (FeatureFlags)0, 1515 false, 1516 }, 1517 { 1518 "unused_multiple_packed", 1519 makeVector(SpecConstant( 7u, "layout(constant_id = ${ID}) const int sc0 = 0;", 4u, makeValueInt32(-999)), 1520 SpecConstant( 1u, "", 0u, GenericValue(), true), 1521 SpecConstant( 3u, "", 0u, GenericValue(), true), 1522 SpecConstant(17u, "layout(constant_id = ${ID}) const int sc1 = 0;", 4u, makeValueInt32( 999))), 1523 8, 1524 " int r0;\n" 1525 " int r1;\n", 1526 "", 1527 " sb_out.r0 = sc0;\n" 1528 " sb_out.r1 = sc1;\n", 1529 makeVector(OffsetValue(4, 0, makeValueInt32(-999)), 1530 OffsetValue(4, 4, makeValueInt32( 999))), 1531 (FeatureFlags)0, 1532 true, 1533 }, 1534 }; 1535 1536 for (const auto& caseDef : defsUnusedCases) 1537 testGroup->addChild(new SpecConstantTest(testCtx, pipelineType, shaderStage, caseDef)); 1538 1539 return testGroup.release(); 1540} 1541 1542//! Specify compute shader work group size through specialization constants. 1543tcu::TestCaseGroup* createWorkGroupSizeTests (tcu::TestContext& testCtx) 1544{ 1545 de::MovePtr<tcu::TestCaseGroup> testGroup (new tcu::TestCaseGroup(testCtx, "local_size", "work group size specialization")); 1546 1547 const deUint32 ssboSize = 16; 1548 const std::string ssboDecl = 1549 " uvec3 workGroupSize;\n" 1550 " uint checksum;\n"; 1551 const std::string globalDecl = "shared uint count;\n"; 1552 const std::string mainCode = 1553 " count = 0u;\n" 1554 "\n" 1555 " groupMemoryBarrier();\n" 1556 " barrier();\n" 1557 "\n" 1558 " atomicAdd(count, 1u);\n" 1559 "\n" 1560 " groupMemoryBarrier();\n" 1561 " barrier();\n" 1562 "\n" 1563 " sb_out.workGroupSize = gl_WorkGroupSize;\n" 1564 " sb_out.checksum = count;\n"; 1565 1566 const CaseDefinition defs[] = 1567 { 1568 { 1569 "x", 1570 makeVector(SpecConstant(1u, "layout(local_size_x_id = ${ID}) in;", 4, makeValueUint32(7u))), 1571 ssboSize, ssboDecl, globalDecl, mainCode, 1572 makeVector(OffsetValue(4, 0, makeValueUint32(7u)), 1573 OffsetValue(4, 4, makeValueUint32(1u)), 1574 OffsetValue(4, 8, makeValueUint32(1u)), 1575 OffsetValue(4, 12, makeValueUint32(7u))), 1576 (FeatureFlags)0, 1577 false, 1578 }, 1579 { 1580 "y", 1581 makeVector(SpecConstant(1u, "layout(local_size_y_id = ${ID}) in;", 4, makeValueUint32(5u))), 1582 ssboSize, ssboDecl, globalDecl, mainCode, 1583 makeVector(OffsetValue(4, 0, makeValueUint32(1u)), 1584 OffsetValue(4, 4, makeValueUint32(5u)), 1585 OffsetValue(4, 8, makeValueUint32(1u)), 1586 OffsetValue(4, 12, makeValueUint32(5u))), 1587 (FeatureFlags)0, 1588 false, 1589 }, 1590 { 1591 "z", 1592 makeVector(SpecConstant(1u, "layout(local_size_z_id = ${ID}) in;", 4, makeValueUint32(3u))), 1593 ssboSize, ssboDecl, globalDecl, mainCode, 1594 makeVector(OffsetValue(4, 0, makeValueUint32(1u)), 1595 OffsetValue(4, 4, makeValueUint32(1u)), 1596 OffsetValue(4, 8, makeValueUint32(3u)), 1597 OffsetValue(4, 12, makeValueUint32(3u))), 1598 (FeatureFlags)0, 1599 false, 1600 }, 1601 { 1602 "xy", 1603 makeVector(SpecConstant(1u, "layout(local_size_x_id = ${ID}) in;", 4, makeValueUint32(6u)), 1604 SpecConstant(2u, "layout(local_size_y_id = ${ID}) in;", 4, makeValueUint32(4u))), 1605 ssboSize, ssboDecl, globalDecl, mainCode, 1606 makeVector(OffsetValue(4, 0, makeValueUint32(6u)), 1607 OffsetValue(4, 4, makeValueUint32(4u)), 1608 OffsetValue(4, 8, makeValueUint32(1u)), 1609 OffsetValue(4, 12, makeValueUint32(6u * 4u))), 1610 (FeatureFlags)0, 1611 false, 1612 }, 1613 { 1614 "xz", 1615 makeVector(SpecConstant(1u, "layout(local_size_x_id = ${ID}) in;", 4, makeValueUint32(3u)), 1616 SpecConstant(2u, "layout(local_size_z_id = ${ID}) in;", 4, makeValueUint32(9u))), 1617 ssboSize, ssboDecl, globalDecl, mainCode, 1618 makeVector(OffsetValue(4, 0, makeValueUint32(3u)), 1619 OffsetValue(4, 4, makeValueUint32(1u)), 1620 OffsetValue(4, 8, makeValueUint32(9u)), 1621 OffsetValue(4, 12, makeValueUint32(3u * 9u))), 1622 (FeatureFlags)0, 1623 false, 1624 }, 1625 { 1626 "yz", 1627 makeVector(SpecConstant(1u, "layout(local_size_y_id = ${ID}) in;", 4, makeValueUint32(2u)), 1628 SpecConstant(2u, "layout(local_size_z_id = ${ID}) in;", 4, makeValueUint32(5u))), 1629 ssboSize, ssboDecl, globalDecl, mainCode, 1630 makeVector(OffsetValue(4, 0, makeValueUint32(1u)), 1631 OffsetValue(4, 4, makeValueUint32(2u)), 1632 OffsetValue(4, 8, makeValueUint32(5u)), 1633 OffsetValue(4, 12, makeValueUint32(2u * 5u))), 1634 (FeatureFlags)0, 1635 false, 1636 }, 1637 { 1638 "xyz", 1639 makeVector(SpecConstant(1u, "layout(local_size_x_id = ${ID}) in;", 4, makeValueUint32(3u)), 1640 SpecConstant(2u, "layout(local_size_y_id = ${ID}) in;", 4, makeValueUint32(5u)), 1641 SpecConstant(3u, "layout(local_size_z_id = ${ID}) in;", 4, makeValueUint32(7u))), 1642 ssboSize, ssboDecl, globalDecl, mainCode, 1643 makeVector(OffsetValue(4, 0, makeValueUint32(3u)), 1644 OffsetValue(4, 4, makeValueUint32(5u)), 1645 OffsetValue(4, 8, makeValueUint32(7u)), 1646 OffsetValue(4, 12, makeValueUint32(3u * 5u * 7u))), 1647 (FeatureFlags)0, 1648 false, 1649 }, 1650 }; 1651 1652 for (int defNdx = 0; defNdx < DE_LENGTH_OF_ARRAY(defs); ++defNdx) 1653 testGroup->addChild(new SpecConstantTest(testCtx, PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC, VK_SHADER_STAGE_COMPUTE_BIT, defs[defNdx])); 1654 1655 return testGroup.release(); 1656} 1657 1658//! Override a built-in variable with specialization constant value. 1659tcu::TestCaseGroup* createBuiltInOverrideTests (tcu::TestContext& testCtx, const PipelineConstructionType pipelineType, const VkShaderStageFlagBits shaderStage) 1660{ 1661 de::MovePtr<tcu::TestCaseGroup> testGroup (new tcu::TestCaseGroup(testCtx, "builtin", "built-in override")); 1662 1663 const CaseDefinition defs[] = 1664 { 1665 { 1666 "default", 1667 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) gl_MaxImageUnits;")), 1668 4, 1669 " bool ok;\n", 1670 "", 1671 " sb_out.ok = (gl_MaxImageUnits >= 8);\n", // implementation defined, 8 is the minimum 1672 makeVector(OffsetValue(4, 0, makeValueBool32(true))), 1673 (FeatureFlags)0, 1674 false, 1675 }, 1676 { 1677 "specialized", 1678 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) gl_MaxImageUnits;", 4, makeValueInt32(12))), 1679 4, 1680 " int maxImageUnits;\n", 1681 "", 1682 " sb_out.maxImageUnits = gl_MaxImageUnits;\n", 1683 makeVector(OffsetValue(4, 0, makeValueInt32(12))), 1684 (FeatureFlags)0, 1685 false, 1686 }, 1687 }; 1688 1689 for (int defNdx = 0; defNdx < DE_LENGTH_OF_ARRAY(defs); ++defNdx) 1690 testGroup->addChild(new SpecConstantTest(testCtx, pipelineType, shaderStage, defs[defNdx])); 1691 1692 return testGroup.release(); 1693} 1694 1695//! Specialization constants used in expressions. 1696tcu::TestCaseGroup* createExpressionTests (tcu::TestContext& testCtx, const PipelineConstructionType pipelineType, const VkShaderStageFlagBits shaderStage) 1697{ 1698 de::MovePtr<tcu::TestCaseGroup> testGroup (new tcu::TestCaseGroup(testCtx, "expression", "specialization constants usage in expressions")); 1699 1700 const CaseDefinition defs[] = 1701 { 1702 { 1703 "spec_const_expression", 1704 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const int sc0 = 2;"), 1705 SpecConstant(2u, "layout(constant_id = ${ID}) const int sc1 = 3;", 4, makeValueInt32(5))), 1706 4, 1707 " int result;\n", 1708 1709 "const int expr0 = sc0 + 1;\n" 1710 "const int expr1 = sc0 + sc1;\n", 1711 1712 " sb_out.result = expr0 + expr1;\n", 1713 makeVector(OffsetValue(4, 0, makeValueInt32(10))), 1714 (FeatureFlags)0, 1715 false, 1716 }, 1717 { 1718 "array_size", 1719 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const int sc0 = 1;"), 1720 SpecConstant(2u, "layout(constant_id = ${ID}) const int sc1 = 2;", 4, makeValueInt32(3))), 1721 16, 1722 " int r0;\n" 1723 " int r1[3];\n", 1724 1725 "", 1726 1727 " int a0[sc0];\n" 1728 " int a1[sc1];\n" 1729 "\n" 1730 " for (int i = 0; i < sc0; ++i)\n" 1731 " a0[i] = sc0 - i;\n" 1732 " for (int i = 0; i < sc1; ++i)\n" 1733 " a1[i] = sc1 - i;\n" 1734 "\n" 1735 " sb_out.r0 = a0[0];\n" 1736 " for (int i = 0; i < sc1; ++i)\n" 1737 " sb_out.r1[i] = a1[i];\n", 1738 makeVector(OffsetValue(4, 0, makeValueInt32(1)), 1739 OffsetValue(4, 4, makeValueInt32(3)), 1740 OffsetValue(4, 8, makeValueInt32(2)), 1741 OffsetValue(4, 12, makeValueInt32(1))), 1742 (FeatureFlags)0, 1743 false, 1744 }, 1745 { 1746 "array_size_expression", 1747 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const int sc0 = 3;"), 1748 SpecConstant(2u, "layout(constant_id = ${ID}) const int sc1 = 5;", 4, makeValueInt32(7))), 1749 8, 1750 " int r0;\n" 1751 " int r1;\n", 1752 1753 "", 1754 1755 " int a0[sc0 + 3];\n" 1756 " int a1[sc0 + sc1];\n" 1757 "\n" 1758 " const int size0 = sc0 + 3;\n" 1759 " const int size1 = sc0 + sc1;\n" 1760 "\n" 1761 " for (int i = 0; i < size0; ++i)\n" 1762 " a0[i] = 3 - i;\n" 1763 " for (int i = 0; i < size1; ++i)\n" 1764 " a1[i] = 5 - i;\n" 1765 "\n" 1766 " sb_out.r0 = a0[size0 - 1];\n" 1767 " sb_out.r1 = a1[size1 - 1];\n", 1768 makeVector(OffsetValue(4, 0, makeValueInt32(-2)), 1769 OffsetValue(4, 4, makeValueInt32(-4))), 1770 (FeatureFlags)0, 1771 false, 1772 }, 1773 { 1774 "array_size_spec_const_expression", 1775 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const int sc0 = 3;"), 1776 SpecConstant(2u, "layout(constant_id = ${ID}) const int sc1 = 5;", 4, makeValueInt32(7))), 1777 8, 1778 " int r0;\n" 1779 " int r1;\n", 1780 1781 "", 1782 1783 " const int size0 = sc0 + 3;\n" 1784 " const int size1 = sc0 + sc1;\n" 1785 "\n" 1786 " int a0[size0];\n" 1787 " int a1[size1];\n" 1788 "\n" 1789 " for (int i = 0; i < size0; ++i)\n" 1790 " a0[i] = 3 - i;\n" 1791 " for (int i = 0; i < size1; ++i)\n" 1792 " a1[i] = 5 - i;\n" 1793 "\n" 1794 " sb_out.r0 = a0[size0 - 1];\n" 1795 " sb_out.r1 = a1[size1 - 1];\n", 1796 makeVector(OffsetValue(4, 0, makeValueInt32(-2)), 1797 OffsetValue(4, 4, makeValueInt32(-4))), 1798 (FeatureFlags)0, 1799 false, 1800 }, 1801 { 1802 "array_size_length", 1803 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const int sc0 = 1;"), 1804 SpecConstant(2u, "layout(constant_id = ${ID}) const int sc1 = 2;", 4, makeValueInt32(4))), 1805 8, 1806 " int r0;\n" 1807 " int r1;\n", 1808 1809 "", 1810 1811 " int a0[sc0];\n" 1812 " int a1[sc1];\n" 1813 "\n" 1814 " sb_out.r0 = a0.length();\n" 1815 " sb_out.r1 = a1.length();\n", 1816 makeVector(OffsetValue(4, 0, makeValueInt32(1)), 1817 OffsetValue(4, 4, makeValueInt32(4))), 1818 (FeatureFlags)0, 1819 false, 1820 }, 1821 { 1822 "array_size_pass_to_function", 1823 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const int sc0 = 3;"), 1824 SpecConstant(2u, "layout(constant_id = ${ID}) const int sc1 = 1;", 4, makeValueInt32(3))), 1825 4, 1826 " int result;\n", 1827 1828 "int sumArrays (int a0[sc0], int a1[sc1])\n" 1829 "{\n" 1830 " int sum = 0;\n" 1831 " for (int i = 0; (i < sc0) && (i < sc1); ++i)\n" 1832 " sum += a0[i] + a1[i];\n" 1833 " return sum;\n" 1834 "}\n", 1835 1836 " int a0[sc0];\n" 1837 " int a1[sc1];\n" 1838 "\n" 1839 " for (int i = 0; i < sc0; ++i)\n" 1840 " a0[i] = i + 1;\n" 1841 " for (int i = 0; i < sc1; ++i)\n" 1842 " a1[i] = i + 2;\n" 1843 "\n" 1844 " sb_out.result = sumArrays(a0, a1);\n", 1845 makeVector(OffsetValue(4, 0, makeValueInt32(15))), 1846 (FeatureFlags)0, 1847 false, 1848 }, 1849 }; 1850 1851 for (int defNdx = 0; defNdx < DE_LENGTH_OF_ARRAY(defs); ++defNdx) 1852 testGroup->addChild(new SpecConstantTest(testCtx, pipelineType, shaderStage, defs[defNdx])); 1853 1854 return testGroup.release(); 1855} 1856 1857//! Helper functions internal to make*CompositeCaseDefinition functions. 1858namespace composite_case_internal 1859{ 1860 1861//! Generate a string like this: "1, 2, sc0, 4" or "true, true, sc0" 1862//! castToType = true is useful when type requires more initializer values than we are providing, e.g.: 1863//! vec2(1), vec2(sc0), vec(3) 1864std::string generateInitializerListWithSpecConstant (const glu::DataType type, 1865 const bool castToType, 1866 const int idxBegin, 1867 const int idxEnd, 1868 const std::string& specConstName, 1869 const int specConstNdx) 1870{ 1871 std::ostringstream str; 1872 1873 for (int i = idxBegin; i < idxEnd; ++i) 1874 { 1875 const std::string iVal = (i == specConstNdx ? specConstName : glu::getDataTypeScalarType(type) == glu::TYPE_BOOL ? "true" : de::toString(i + 1)); 1876 str << (i != idxBegin ? ", " : "") << (castToType ? de::toString(glu::getDataTypeName(type)) + "(" + iVal + ")" : iVal); 1877 } 1878 1879 return str.str(); 1880} 1881 1882std::string generateArrayConstructorString (const glu::DataType elemType, 1883 const int size1, 1884 const int size2, 1885 const std::string& specConstName, 1886 const int specConstNdx) 1887{ 1888 const bool isArrayOfArray = (size2 > 0); 1889 const bool doCast = (!isDataTypeScalar(elemType)); 1890 1891 std::ostringstream arrayCtorExpr; 1892 1893 if (isArrayOfArray) 1894 { 1895 const std::string padding (36, ' '); 1896 int idxBegin = 0; 1897 int idxEnd = size2; 1898 1899 for (int iterNdx = 0; iterNdx < size1; ++iterNdx) 1900 { 1901 // Open sub-array ctor 1902 arrayCtorExpr << (iterNdx != 0 ? ",\n" + padding : "") << glu::getDataTypeName(elemType) << "[" << size2 << "]("; 1903 1904 // Sub-array constructor elements 1905 arrayCtorExpr << generateInitializerListWithSpecConstant(elemType, doCast, idxBegin, idxEnd, specConstName, specConstNdx); 1906 1907 // Close sub-array ctor, move to next range 1908 arrayCtorExpr << ")"; 1909 1910 idxBegin += size2; 1911 idxEnd += size2; 1912 } 1913 } 1914 else 1915 { 1916 // Array constructor elements 1917 arrayCtorExpr << generateInitializerListWithSpecConstant(elemType, doCast, 0, size1, specConstName, specConstNdx); 1918 } 1919 1920 return arrayCtorExpr.str(); 1921} 1922 1923inline GenericValue makeValue (const glu::DataType type, const int specValue) 1924{ 1925 if (type == glu::TYPE_DOUBLE) 1926 return makeValueFloat64(static_cast<double>(specValue)); 1927 else if (type == glu::TYPE_FLOAT) 1928 return makeValueFloat32(static_cast<float>(specValue)); 1929 else 1930 return makeValueInt32(specValue); 1931} 1932 1933deUint32 getDataTypeScalarSizeBytes (const glu::DataType dataType) 1934{ 1935 switch (getDataTypeScalarType(dataType)) 1936 { 1937 case glu::TYPE_FLOAT: 1938 case glu::TYPE_INT: 1939 case glu::TYPE_UINT: 1940 case glu::TYPE_BOOL: 1941 return 4; 1942 1943 case glu::TYPE_DOUBLE: 1944 return 8; 1945 1946 default: 1947 DE_ASSERT(false); 1948 return 0; 1949 } 1950} 1951 1952//! This applies to matrices/vectors/array cases. dataType must be a basic type. 1953std::vector<OffsetValue> computeExpectedValues (const int specValue, const glu::DataType dataType, const int numCombinations) 1954{ 1955 DE_ASSERT(glu::isDataTypeScalar(dataType)); 1956 1957 std::vector<OffsetValue> expectedValues; 1958 1959 for (int combNdx = 0; combNdx < numCombinations; ++combNdx) 1960 { 1961 int sum = 0; 1962 for (int i = 0; i < numCombinations; ++i) 1963 sum += (i == combNdx ? specValue : dataType == glu::TYPE_BOOL ? 1 : (i + 1)); 1964 1965 const int dataSize = getDataTypeScalarSizeBytes(dataType); 1966 expectedValues.push_back(OffsetValue(dataSize, dataSize * combNdx, makeValue(dataType, sum))); 1967 } 1968 1969 return expectedValues; 1970} 1971 1972inline std::string getFirstDataElementSubscriptString (const glu::DataType type) 1973{ 1974 // Grab the first element of a matrix/vector, if dealing with non-basic types. 1975 return (isDataTypeMatrix(type) ? "[0][0]" : isDataTypeVector(type) ? "[0]" : ""); 1976} 1977 1978//! This code will go into the main function. 1979std::string generateShaderChecksumComputationCode (const glu::DataType elemType, 1980 const std::string& varName, 1981 const std::string& accumType, 1982 const int size1, 1983 const int size2, 1984 const int numCombinations) 1985{ 1986 std::ostringstream mainCode; 1987 1988 // Generate main code to calculate checksums for each array 1989 for (int combNdx = 0; combNdx < numCombinations; ++combNdx) 1990 mainCode << " "<< accumType << " sum_" << varName << combNdx << " = " << accumType << "(0);\n"; 1991 1992 if (size2 > 0) 1993 { 1994 mainCode << "\n" 1995 << " for (int i = 0; i < " << size1 << "; ++i)\n" 1996 << " for (int j = 0; j < " << size2 << "; ++j)\n" 1997 << " {\n"; 1998 1999 for (int combNdx = 0; combNdx < numCombinations; ++combNdx) 2000 mainCode << " sum_" << varName << combNdx << " += " << accumType << "(" 2001 << varName << combNdx << "[i][j]" << getFirstDataElementSubscriptString(elemType) << ");\n"; 2002 } 2003 else 2004 { 2005 mainCode << "\n" 2006 << " for (int i = 0; i < " << size1 << "; ++i)\n" 2007 << " {\n"; 2008 2009 for (int combNdx = 0; combNdx < numCombinations; ++combNdx) 2010 mainCode << " sum_" << varName << combNdx << " += " << accumType << "(" 2011 << varName << combNdx << "[i]" << getFirstDataElementSubscriptString(elemType) << ");\n"; 2012 } 2013 2014 mainCode << " }\n" 2015 << "\n"; 2016 2017 for (int combNdx = 0; combNdx < numCombinations; ++combNdx) 2018 mainCode << " sb_out.result[" << combNdx << "] = sum_" << varName << combNdx << ";\n"; 2019 2020 return mainCode.str(); 2021} 2022 2023SpecConstant makeSpecConstant (const std::string specConstName, const deUint32 specConstId, const glu::DataType type, const int specValue) 2024{ 2025 DE_ASSERT(glu::isDataTypeScalar(type)); 2026 2027 const std::string typeName(glu::getDataTypeName(type)); 2028 2029 return SpecConstant( 2030 specConstId, 2031 "layout(constant_id = ${ID}) const " + typeName + " " + specConstName + " = " + typeName + "(1);", 2032 getDataTypeScalarSizeBytes(type), makeValue(type, specValue)); 2033} 2034 2035} // composite_case_internal ns 2036 2037//! Generate a CaseDefinition for a composite test using a matrix or vector (a 1-column matrix) 2038CaseDefinition makeMatrixVectorCompositeCaseDefinition (const glu::DataType type) 2039{ 2040 using namespace composite_case_internal; 2041 2042 DE_ASSERT(!glu::isDataTypeScalar(type)); 2043 2044 const std::string varName = (glu::isDataTypeMatrix(type) ? "m" : "v"); 2045 const int numCombinations = getDataTypeScalarSize(type); 2046 const glu::DataType scalarType = glu::getDataTypeScalarType(type); 2047 const std::string typeName = glu::getDataTypeName(type); 2048 const bool isConst = (scalarType != glu::TYPE_FLOAT) && (scalarType != glu::TYPE_DOUBLE); 2049 2050 std::ostringstream globalCode; 2051 { 2052 // Build N matrices/vectors with specialization constant inserted at various locations in the constructor. 2053 for (int combNdx = 0; combNdx < numCombinations; ++combNdx) 2054 globalCode << ( isConst ? "const " : "" ) << typeName << " " << varName << combNdx << " = " << typeName << "(" 2055 << generateInitializerListWithSpecConstant(type, false, 0, numCombinations, "sc0", combNdx) << ");\n"; 2056 } 2057 2058 const bool isBoolElement = (scalarType == glu::TYPE_BOOL); 2059 const int specValue = (isBoolElement ? 0 : 42); 2060 const std::string accumType = glu::getDataTypeName(isBoolElement ? glu::TYPE_INT : scalarType); 2061 2062 const int size1 = glu::isDataTypeMatrix(type) ? glu::getDataTypeMatrixNumColumns(type) : glu::getDataTypeNumComponents(type); 2063 const int size2 = glu::isDataTypeMatrix(type) ? glu::getDataTypeMatrixNumRows(type) : 0; 2064 2065 const CaseDefinition def = 2066 { 2067 typeName, 2068 makeVector(makeSpecConstant("sc0", 1u, scalarType, specValue)), 2069 static_cast<VkDeviceSize>(getDataTypeScalarSizeBytes(type) * numCombinations), 2070 " " + accumType + " result[" + de::toString(numCombinations) + "];\n", 2071 globalCode.str(), 2072 generateShaderChecksumComputationCode(scalarType, varName, accumType, size1, size2, numCombinations), 2073 computeExpectedValues(specValue, scalarType, numCombinations), 2074 (scalarType == glu::TYPE_DOUBLE ? (FeatureFlags)FEATURE_SHADER_FLOAT_64 : (FeatureFlags)0), 2075 false, 2076 }; 2077 return def; 2078} 2079 2080//! Generate a CaseDefinition for a composite test using an array, or an array of array. 2081//! If (size1, size2) = (N, 0) -> type array[N] 2082//! = (N, M) -> type array[N][M] 2083CaseDefinition makeArrayCompositeCaseDefinition (const glu::DataType elemType, const int size1, const int size2 = 0) 2084{ 2085 using namespace composite_case_internal; 2086 2087 DE_ASSERT(size1 > 0); 2088 2089 const bool isArrayOfArray = (size2 > 0); 2090 const std::string varName = "a"; 2091 const std::string arraySizeDecl = "[" + de::toString(size1) + "]" + (isArrayOfArray ? "[" + de::toString(size2) + "]" : ""); 2092 const int numCombinations = (isArrayOfArray ? size1 * size2 : size1); 2093 const std::string elemTypeName (glu::getDataTypeName(elemType)); 2094 2095 std::ostringstream globalCode; 2096 { 2097 // Create several arrays with specialization constant inserted in different positions. 2098 for (int combNdx = 0; combNdx < numCombinations; ++combNdx) 2099 globalCode << elemTypeName << " " << varName << combNdx << arraySizeDecl << " = " 2100 << elemTypeName << arraySizeDecl << "(" << generateArrayConstructorString(elemType, size1, size2, "sc0", combNdx) << ");\n"; 2101 } 2102 2103 const glu::DataType scalarType = glu::getDataTypeScalarType(elemType); 2104 const bool isBoolData = (scalarType == glu::TYPE_BOOL); 2105 const int specValue = (isBoolData ? 0 : 19); 2106 const std::string caseName = (isArrayOfArray ? "array_" : "") + elemTypeName; 2107 const std::string accumType = (glu::getDataTypeName(isBoolData ? glu::TYPE_INT : scalarType)); 2108 2109 const CaseDefinition def = 2110 { 2111 caseName, 2112 makeVector(makeSpecConstant("sc0", 1u, scalarType, specValue)), 2113 static_cast<VkDeviceSize>(getDataTypeScalarSizeBytes(elemType) * numCombinations), 2114 " " + accumType + " result[" + de::toString(numCombinations) + "];\n", 2115 globalCode.str(), 2116 generateShaderChecksumComputationCode(elemType, varName, accumType, size1, size2, numCombinations), 2117 computeExpectedValues(specValue, scalarType, numCombinations), 2118 (scalarType == glu::TYPE_DOUBLE ? (FeatureFlags)FEATURE_SHADER_FLOAT_64 : (FeatureFlags)0), 2119 false, 2120 }; 2121 return def; 2122} 2123 2124//! A basic struct case, where one member is a specialization constant, or a specialization constant composite 2125//! (a matrix/vector with a spec. const. element). 2126CaseDefinition makeStructCompositeCaseDefinition (const glu::DataType memberType) 2127{ 2128 using namespace composite_case_internal; 2129 2130 std::ostringstream globalCode; 2131 { 2132 globalCode << "struct Data {\n" 2133 << " int i;\n" 2134 << " float f;\n" 2135 << " bool b;\n" 2136 << " " << glu::getDataTypeName(memberType) << " sc;\n" 2137 << " uint ui;\n" 2138 << "};\n" 2139 << "\n" 2140 << "Data s0 = Data(3, 2.0, true, " << glu::getDataTypeName(memberType) << "(sc0), 8u);\n"; 2141 } 2142 2143 const glu::DataType scalarType = glu::getDataTypeScalarType(memberType); 2144 const bool isBoolData = (scalarType == glu::TYPE_BOOL); 2145 const int specValue = (isBoolData ? 0 : 23); 2146 const int checksum = (3 + 2 + 1 + specValue + 8); // matches the shader code 2147 const glu::DataType accumType = (isBoolData ? glu::TYPE_INT : scalarType); 2148 const std::string accumTypeStr = glu::getDataTypeName(accumType); 2149 2150 std::ostringstream mainCode; 2151 { 2152 mainCode << " " << accumTypeStr << " sum_s0 = " << accumTypeStr << "(0);\n" 2153 << "\n" 2154 << " sum_s0 += " << accumTypeStr << "(s0.i);\n" 2155 << " sum_s0 += " << accumTypeStr << "(s0.f);\n" 2156 << " sum_s0 += " << accumTypeStr << "(s0.b);\n" 2157 << " sum_s0 += " << accumTypeStr << "(s0.sc" << getFirstDataElementSubscriptString(memberType) << ");\n" 2158 << " sum_s0 += " << accumTypeStr << "(s0.ui);\n" 2159 << "\n" 2160 << " sb_out.result = sum_s0;\n"; 2161 } 2162 2163 const std::string caseName = glu::getDataTypeName(memberType); 2164 2165 const CaseDefinition def = 2166 { 2167 caseName, 2168 makeVector(makeSpecConstant("sc0", 1u, scalarType, specValue)), 2169 getDataTypeScalarSizeBytes(accumType), 2170 " " + accumTypeStr + " result;\n", 2171 globalCode.str(), 2172 mainCode.str(), 2173 makeVector(OffsetValue(getDataTypeScalarSizeBytes(memberType), 0, makeValue(scalarType, checksum))), 2174 (scalarType == glu::TYPE_DOUBLE ? (FeatureFlags)FEATURE_SHADER_FLOAT_64 : (FeatureFlags)0), 2175 false, 2176 }; 2177 return def; 2178} 2179 2180//! Specialization constants used in composites. 2181tcu::TestCaseGroup* createCompositeTests (tcu::TestContext& testCtx, const PipelineConstructionType pipelineType, const VkShaderStageFlagBits shaderStage) 2182{ 2183 de::MovePtr<tcu::TestCaseGroup> compositeTests (new tcu::TestCaseGroup(testCtx, "composite", "specialization constants usage in composite types")); 2184 2185 // Vectors 2186 { 2187 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "vector")); 2188 2189 const glu::DataType types[] = 2190 { 2191 glu::TYPE_FLOAT_VEC2, 2192 glu::TYPE_FLOAT_VEC3, 2193 glu::TYPE_FLOAT_VEC4, 2194 2195 glu::TYPE_DOUBLE_VEC2, 2196 glu::TYPE_DOUBLE_VEC3, 2197 glu::TYPE_DOUBLE_VEC4, 2198 2199 glu::TYPE_BOOL_VEC2, 2200 glu::TYPE_BOOL_VEC3, 2201 glu::TYPE_BOOL_VEC4, 2202 2203 glu::TYPE_INT_VEC2, 2204 glu::TYPE_INT_VEC3, 2205 glu::TYPE_INT_VEC4, 2206 2207 glu::TYPE_UINT_VEC2, 2208 glu::TYPE_UINT_VEC3, 2209 glu::TYPE_UINT_VEC4, 2210 }; 2211 for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(types); ++typeNdx) 2212 group->addChild(new SpecConstantTest(testCtx, pipelineType, shaderStage, makeMatrixVectorCompositeCaseDefinition(types[typeNdx]))); 2213 2214 compositeTests->addChild(group.release()); 2215 } 2216 2217 // Matrices 2218 { 2219 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "matrix")); 2220 2221 const glu::DataType types[] = 2222 { 2223 glu::TYPE_FLOAT_MAT2, 2224 glu::TYPE_FLOAT_MAT2X3, 2225 glu::TYPE_FLOAT_MAT2X4, 2226 glu::TYPE_FLOAT_MAT3X2, 2227 glu::TYPE_FLOAT_MAT3, 2228 glu::TYPE_FLOAT_MAT3X4, 2229 glu::TYPE_FLOAT_MAT4X2, 2230 glu::TYPE_FLOAT_MAT4X3, 2231 glu::TYPE_FLOAT_MAT4, 2232 2233 glu::TYPE_DOUBLE_MAT2, 2234 glu::TYPE_DOUBLE_MAT2X3, 2235 glu::TYPE_DOUBLE_MAT2X4, 2236 glu::TYPE_DOUBLE_MAT3X2, 2237 glu::TYPE_DOUBLE_MAT3, 2238 glu::TYPE_DOUBLE_MAT3X4, 2239 glu::TYPE_DOUBLE_MAT4X2, 2240 glu::TYPE_DOUBLE_MAT4X3, 2241 glu::TYPE_DOUBLE_MAT4, 2242 }; 2243 for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(types); ++typeNdx) 2244 group->addChild(new SpecConstantTest(testCtx, pipelineType, shaderStage, makeMatrixVectorCompositeCaseDefinition(types[typeNdx]))); 2245 2246 compositeTests->addChild(group.release()); 2247 } 2248 2249 const glu::DataType allTypes[] = 2250 { 2251 glu::TYPE_FLOAT, 2252 glu::TYPE_FLOAT_VEC2, 2253 glu::TYPE_FLOAT_VEC3, 2254 glu::TYPE_FLOAT_VEC4, 2255 glu::TYPE_FLOAT_MAT2, 2256 glu::TYPE_FLOAT_MAT2X3, 2257 glu::TYPE_FLOAT_MAT2X4, 2258 glu::TYPE_FLOAT_MAT3X2, 2259 glu::TYPE_FLOAT_MAT3, 2260 glu::TYPE_FLOAT_MAT3X4, 2261 glu::TYPE_FLOAT_MAT4X2, 2262 glu::TYPE_FLOAT_MAT4X3, 2263 glu::TYPE_FLOAT_MAT4, 2264 2265 glu::TYPE_DOUBLE, 2266 glu::TYPE_DOUBLE_VEC2, 2267 glu::TYPE_DOUBLE_VEC3, 2268 glu::TYPE_DOUBLE_VEC4, 2269 glu::TYPE_DOUBLE_MAT2, 2270 glu::TYPE_DOUBLE_MAT2X3, 2271 glu::TYPE_DOUBLE_MAT2X4, 2272 glu::TYPE_DOUBLE_MAT3X2, 2273 glu::TYPE_DOUBLE_MAT3, 2274 glu::TYPE_DOUBLE_MAT3X4, 2275 glu::TYPE_DOUBLE_MAT4X2, 2276 glu::TYPE_DOUBLE_MAT4X3, 2277 glu::TYPE_DOUBLE_MAT4, 2278 2279 glu::TYPE_INT, 2280 glu::TYPE_INT_VEC2, 2281 glu::TYPE_INT_VEC3, 2282 glu::TYPE_INT_VEC4, 2283 2284 glu::TYPE_UINT, 2285 glu::TYPE_UINT_VEC2, 2286 glu::TYPE_UINT_VEC3, 2287 glu::TYPE_UINT_VEC4, 2288 2289 glu::TYPE_BOOL, 2290 glu::TYPE_BOOL_VEC2, 2291 glu::TYPE_BOOL_VEC3, 2292 glu::TYPE_BOOL_VEC4, 2293 }; 2294 2295 // Array cases 2296 { 2297 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "array")); 2298 2299 // Array of T 2300 for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(allTypes); ++typeNdx) 2301 group->addChild(new SpecConstantTest(testCtx, pipelineType, shaderStage, makeArrayCompositeCaseDefinition(allTypes[typeNdx], 3))); 2302 2303 // Array of array of T 2304 for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(allTypes); ++typeNdx) 2305 group->addChild(new SpecConstantTest(testCtx, pipelineType, shaderStage, makeArrayCompositeCaseDefinition(allTypes[typeNdx], 3, 2))); 2306 2307 // Special case - array of struct 2308 { 2309 const int checksum = (3 + 2 + 1) + (1 + 5 + 1) + (1 + 2 + 0); 2310 const CaseDefinition def = 2311 { 2312 "struct", 2313 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const int sc0 = 1;", 4, makeValueInt32 (3)), 2314 SpecConstant(2u, "layout(constant_id = ${ID}) const float sc1 = 1.0;", 4, makeValueFloat32(5.0f)), 2315 SpecConstant(3u, "layout(constant_id = ${ID}) const bool sc2 = true;", 4, makeValueBool32 (false))), 2316 4, 2317 " int result;\n", 2318 2319 "struct Data {\n" 2320 " int x;\n" 2321 " float y;\n" 2322 " bool z;\n" 2323 "};\n" 2324 "\n" 2325 "Data a0[3] = Data[3](Data(sc0, 2.0, true), Data(1, sc1, true), Data(1, 2.0, sc2));\n", 2326 2327 " int sum_a0 = 0;\n" 2328 "\n" 2329 " for (int i = 0; i < 3; ++i)\n" 2330 " sum_a0 += int(a0[i].x) + int(a0[i].y) + int(a0[i].z);\n" 2331 "\n" 2332 " sb_out.result = sum_a0;\n", 2333 2334 makeVector(OffsetValue(4, 0, makeValueInt32(checksum))), 2335 (FeatureFlags)0, 2336 false, 2337 }; 2338 2339 group->addChild(new SpecConstantTest(testCtx, pipelineType, shaderStage, def)); 2340 } 2341 2342 compositeTests->addChild(group.release()); 2343 } 2344 2345 // Struct cases 2346 { 2347 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "struct")); 2348 2349 // Struct with one member being a specialization constant (or spec. const. composite) of a given type 2350 for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(allTypes); ++typeNdx) 2351 group->addChild(new SpecConstantTest(testCtx, pipelineType, shaderStage, makeStructCompositeCaseDefinition(allTypes[typeNdx]))); 2352 2353 // Special case - struct with array 2354 { 2355 const int checksum = (1 + 2 + 31 + 4 + 0); 2356 const CaseDefinition def = 2357 { 2358 "array", 2359 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const float sc0 = 1.0;", 4, makeValueFloat32(31.0f))), 2360 4, 2361 " float result;\n", 2362 2363 "struct Data {\n" 2364 " int i;\n" 2365 " vec3 sc[3];\n" 2366 " bool b;\n" 2367 "};\n" 2368 "\n" 2369 "Data s0 = Data(1, vec3[3](vec3(2.0), vec3(sc0), vec3(4.0)), false);\n", 2370 2371 " float sum_s0 = 0;\n" 2372 "\n" 2373 " sum_s0 += float(s0.i);\n" 2374 " sum_s0 += float(s0.sc[0][0]);\n" 2375 " sum_s0 += float(s0.sc[1][0]);\n" 2376 " sum_s0 += float(s0.sc[2][0]);\n" 2377 " sum_s0 += float(s0.b);\n" 2378 "\n" 2379 " sb_out.result = sum_s0;\n", 2380 2381 makeVector(OffsetValue(4, 0, makeValueFloat32(static_cast<float>(checksum)))), 2382 (FeatureFlags)0, 2383 false, 2384 }; 2385 2386 group->addChild(new SpecConstantTest(testCtx, pipelineType, shaderStage, def)); 2387 } 2388 2389 // Special case - struct of struct 2390 { 2391 const int checksum = (1 + 2 + 11 + 4 + 1); 2392 const CaseDefinition def = 2393 { 2394 "struct", 2395 makeVector(SpecConstant(1u, "layout(constant_id = ${ID}) const int sc0 = 1;", 4, makeValueInt32(11))), 2396 4, 2397 " int result;\n", 2398 2399 "struct Nested {\n" 2400 " vec2 v;\n" 2401 " int sc;\n" 2402 " float f;\n" 2403 "};\n" 2404 "\n" 2405 "struct Data {\n" 2406 " uint ui;\n" 2407 " Nested s;\n" 2408 " bool b;\n" 2409 "};\n" 2410 "\n" 2411 "Data s0 = Data(1u, Nested(vec2(2.0), sc0, 4.0), true);\n", 2412 2413 " int sum_s0 = 0;\n" 2414 "\n" 2415 " sum_s0 += int(s0.ui);\n" 2416 " sum_s0 += int(s0.s.v[0]);\n" 2417 " sum_s0 += int(s0.s.sc);\n" 2418 " sum_s0 += int(s0.s.f);\n" 2419 " sum_s0 += int(s0.b);\n" 2420 "\n" 2421 " sb_out.result = sum_s0;\n", 2422 2423 makeVector(OffsetValue(4, 0, makeValueInt32(checksum))), 2424 (FeatureFlags)0, 2425 false, 2426 }; 2427 2428 group->addChild(new SpecConstantTest(testCtx, pipelineType, shaderStage, def)); 2429 } 2430 2431 compositeTests->addChild(group.release()); 2432 } 2433 2434 return compositeTests.release(); 2435} 2436 2437} // anonymous ns 2438 2439tcu::TestCaseGroup* createSpecConstantTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineType) 2440{ 2441 de::MovePtr<tcu::TestCaseGroup> allTests (new tcu::TestCaseGroup(testCtx, "spec_constant", "Specialization constants tests")); 2442 de::MovePtr<tcu::TestCaseGroup> graphicsGroup (new tcu::TestCaseGroup(testCtx, "graphics")); 2443 2444 struct StageDef 2445 { 2446 tcu::TestCaseGroup* parentGroup; 2447 const char* name; 2448 VkShaderStageFlagBits stage; 2449 }; 2450 2451 const StageDef stages[] = 2452 { 2453 { graphicsGroup.get(), "vertex", VK_SHADER_STAGE_VERTEX_BIT }, 2454 { graphicsGroup.get(), "fragment", VK_SHADER_STAGE_FRAGMENT_BIT }, 2455 { graphicsGroup.get(), "tess_control", VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT }, 2456 { graphicsGroup.get(), "tess_eval", VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT }, 2457 { graphicsGroup.get(), "geometry", VK_SHADER_STAGE_GEOMETRY_BIT }, 2458 { allTests.get(), "compute", VK_SHADER_STAGE_COMPUTE_BIT }, 2459 }; 2460 2461 allTests->addChild(graphicsGroup.release()); 2462 2463 for (int stageNdx = 0; stageNdx < DE_LENGTH_OF_ARRAY(stages); ++stageNdx) 2464 { 2465 const StageDef& stage = stages[stageNdx]; 2466 const bool isCompute = (stage.stage == VK_SHADER_STAGE_COMPUTE_BIT); 2467 2468 if (isCompute && (pipelineType != PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)) 2469 continue; 2470 2471 de::MovePtr<tcu::TestCaseGroup> stageGroup (new tcu::TestCaseGroup(testCtx, stage.name)); 2472 2473 stageGroup->addChild(createDefaultValueTests (testCtx, pipelineType, stage.stage)); 2474 stageGroup->addChild(createBasicSpecializationTests (testCtx, pipelineType, stage.stage)); 2475 stageGroup->addChild(createBuiltInOverrideTests (testCtx, pipelineType, stage.stage)); 2476 stageGroup->addChild(createExpressionTests (testCtx, pipelineType, stage.stage)); 2477 stageGroup->addChild(createCompositeTests (testCtx, pipelineType, stage.stage)); 2478 2479 if (isCompute) 2480 stageGroup->addChild(createWorkGroupSizeTests(testCtx)); 2481 2482 stage.parentGroup->addChild(stageGroup.release()); 2483 } 2484 2485 return allTests.release(); 2486} 2487 2488} // pipeline 2489} // vkt 2490