1/*------------------------------------------------------------------------ 2 * Vulkan Conformance Tests 3 * ------------------------ 4 * 5 * Copyright (c) 2023 LunarG, Inc. 6 * Copyright (c) 2023 Nintendo 7 * 8 * Licensed under the Apache License, Version 2.0 (the "License"); 9 * you may not use this file except in compliance with the License. 10 * You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 * 20 *//*! 21 * \file 22 * \brief Shader Object Create Tests 23 *//*--------------------------------------------------------------------*/ 24 25#include "vktShaderObjectCreateTests.hpp" 26#include "deUniquePtr.hpp" 27#include "tcuTestCase.hpp" 28#include "vktTestCase.hpp" 29#include "vkQueryUtil.hpp" 30#include "vktCustomInstancesDevices.hpp" 31#include "tcuCommandLine.hpp" 32#include "vkBufferWithMemory.hpp" 33#include "vkRefUtil.hpp" 34#include "deRandom.hpp" 35#include "vktShaderObjectCreateUtil.hpp" 36#include "vkBuilderUtil.hpp" 37 38namespace vkt 39{ 40namespace ShaderObject 41{ 42 43namespace 44{ 45 46class ShaderObjectCreateInstance : public vkt::TestInstance 47{ 48public: 49 ShaderObjectCreateInstance (Context& context, const bool useMeshShaders) 50 : vkt::TestInstance (context) 51 , m_useMeshShaders (useMeshShaders) 52 {} 53 virtual ~ShaderObjectCreateInstance (void) {} 54 55 tcu::TestStatus iterate (void) override; 56 57private: 58 const bool m_useMeshShaders; 59}; 60 61tcu::TestStatus ShaderObjectCreateInstance::iterate (void) 62{ 63 const vk::VkInstance instance = m_context.getInstance(); 64 const vk::InstanceDriver instanceDriver (m_context.getPlatformInterface(), instance); 65 const vk::DeviceInterface& vk = m_context.getDeviceInterface(); 66 const vk::VkDevice device = m_context.getDevice(); 67 tcu::TestLog& log = m_context.getTestContext().getLog(); 68 const bool tessellationSupported = m_context.getDeviceFeatures().tessellationShader; 69 const bool geometrySupported = m_context.getDeviceFeatures().geometryShader; 70 71 const auto& binaries = m_context.getBinaryCollection(); 72 const auto& vert = binaries.get("vert"); 73 const auto& tesc = binaries.get("tesc"); 74 const auto& tese = binaries.get("tese"); 75 const auto& geom = binaries.get("geom"); 76 const auto& frag = binaries.get("frag"); 77 const auto& comp = binaries.get("comp"); 78 79 const vk::VkDescriptorSetLayoutBinding layoutBinding = 80 { 81 0u, // deUint32 binding; 82 vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, // VkDescriptorType descriptorType; 83 1u, // deUint32 arraySize; 84 vk::VK_SHADER_STAGE_COMPUTE_BIT, // VkShaderStageFlags stageFlags; 85 DE_NULL // const VkSampler* pImmutableSamplers; 86 }; 87 88 const vk::VkDescriptorSetLayoutCreateInfo descriptorLayoutParams = 89 { 90 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // VkStructureType sType; 91 DE_NULL, // const void* pNext; 92 (vk::VkDescriptorSetLayoutCreateFlags)0, // VkDescriptorSetLayoutCreateFlags flags; 93 1u, // deUint32 count; 94 &layoutBinding // const VkDescriptorSetLayoutBinding pBinding; 95 }; 96 97 const auto descriptorSetLayout = vk::createDescriptorSetLayout(vk, device, &descriptorLayoutParams); 98 99 // Todo: remove const_cast if spec is updated 100 vk::VkDescriptorSetLayout* setLayout = const_cast<vk::VkDescriptorSetLayout*>(&descriptorSetLayout.get()); 101 102 std::vector<vk::VkShaderCreateInfoEXT> shaderCreateInfos = 103 { 104 { 105 vk::VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT, // VkStructureType sType; 106 DE_NULL, // const void* pNext; 107 0u, // VkShaderCreateFlagsEXT flags; 108 vk::VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage; 109 vk::getShaderObjectNextStages(vk::VK_SHADER_STAGE_VERTEX_BIT, tessellationSupported, geometrySupported), // VkShaderStageFlags nextStage; 110 vk::VK_SHADER_CODE_TYPE_SPIRV_EXT, // VkShaderCodeTypeEXT codeType; 111 vert.getSize(), // size_t codeSize; 112 vert.getBinary(), // const void* pCode; 113 "main", // const char* pName; 114 0u, // uint32_t setLayoutCount; 115 DE_NULL, // VkDescriptorSetLayout* pSetLayouts; 116 0u, // uint32_t pushConstantRangeCount; 117 DE_NULL, // const VkPushConstantRange* pPushConstantRanges; 118 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo; 119 }, 120 { 121 vk::VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT, // VkStructureType sType; 122 DE_NULL, // const void* pNext; 123 0u, // VkShaderCreateFlagsEXT flags; 124 vk::VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage; 125 vk::getShaderObjectNextStages(vk::VK_SHADER_STAGE_FRAGMENT_BIT, tessellationSupported, geometrySupported), // VkShaderStageFlags nextStage; 126 vk::VK_SHADER_CODE_TYPE_SPIRV_EXT, // VkShaderCodeTypeEXT codeType; 127 frag.getSize(), // size_t codeSize; 128 frag.getBinary(), // const void* pCode; 129 "main", // const char* pName; 130 0u, // uint32_t setLayoutCount; 131 DE_NULL, // VkDescriptorSetLayout* pSetLayouts; 132 0u, // uint32_t pushConstantRangeCount; 133 DE_NULL, // const VkPushConstantRange* pPushConstantRanges; 134 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo; 135 }, 136 { 137 vk::VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT, // VkStructureType sType; 138 DE_NULL, // const void* pNext; 139 0u, // VkShaderCreateFlagsEXT flags; 140 vk::VK_SHADER_STAGE_COMPUTE_BIT, // VkShaderStageFlagBits stage; 141 0u, // VkShaderStageFlags nextStage; 142 vk::VK_SHADER_CODE_TYPE_SPIRV_EXT, // VkShaderCodeTypeEXT codeType; 143 comp.getSize(), // size_t codeSize; 144 comp.getBinary(), // const void* pCode; 145 "main", // const char* pName; 146 1u, // uint32_t setLayoutCount; 147 setLayout, // VkDescriptorSetLayout* pSetLayouts; 148 0u, // uint32_t pushConstantRangeCount; 149 DE_NULL, // const VkPushConstantRange* pPushConstantRanges; 150 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo; 151 }, 152 }; 153 154 if (m_context.getDeviceFeatures().tessellationShader) 155 { 156 shaderCreateInfos.push_back( 157 { 158 vk::VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT, // VkStructureType sType; 159 DE_NULL, // const void* pNext; 160 0u, // VkShaderCreateFlagsEXT flags; 161 vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, // VkShaderStageFlagBits stage; 162 vk::getShaderObjectNextStages(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, tessellationSupported, geometrySupported), // VkShaderStageFlags nextStage; 163 vk::VK_SHADER_CODE_TYPE_SPIRV_EXT, // VkShaderCodeTypeEXT codeType; 164 tesc.getSize(), // size_t codeSize; 165 tesc.getBinary(), // const void* pCode; 166 "main", // const char* pName; 167 0u, // uint32_t setLayoutCount; 168 DE_NULL, // VkDescriptorSetLayout* pSetLayouts; 169 0u, // uint32_t pushConstantRangeCount; 170 DE_NULL, // const VkPushConstantRange* pPushConstantRanges; 171 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo; 172 } 173 ); 174 shaderCreateInfos.push_back( 175 { 176 vk::VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT, // VkStructureType sType; 177 DE_NULL, // const void* pNext; 178 0u, // VkShaderCreateFlagsEXT flags; 179 vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,// VkShaderStageFlagBits stage; 180 vk::getShaderObjectNextStages(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, tessellationSupported, geometrySupported), // VkShaderStageFlags nextStage; 181 vk::VK_SHADER_CODE_TYPE_SPIRV_EXT, // VkShaderCodeTypeEXT codeType; 182 tese.getSize(), // size_t codeSize; 183 tese.getBinary(), // const void* pCode; 184 "main", // const char* pName; 185 0u, // uint32_t setLayoutCount; 186 DE_NULL, // VkDescriptorSetLayout* pSetLayouts; 187 0u, // uint32_t pushConstantRangeCount; 188 DE_NULL, // const VkPushConstantRange* pPushConstantRanges; 189 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo; 190 } 191 ); 192 } 193 194 if (m_context.getDeviceFeatures().geometryShader) 195 { 196 shaderCreateInfos.push_back( 197 { 198 vk::VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT, // VkStructureType sType; 199 DE_NULL, // const void* pNext; 200 0u, // VkShaderCreateFlagsEXT flags; 201 vk::VK_SHADER_STAGE_GEOMETRY_BIT, // VkShaderStageFlagBits stage; 202 vk::getShaderObjectNextStages(vk::VK_SHADER_STAGE_GEOMETRY_BIT, tessellationSupported, geometrySupported), // VkShaderStageFlags nextStage; 203 vk::VK_SHADER_CODE_TYPE_SPIRV_EXT, // VkShaderCodeTypeEXT codeType; 204 geom.getSize(), // size_t codeSize; 205 geom.getBinary(), // const void* pCode; 206 "main", // const char* pName; 207 0u, // uint32_t setLayoutCount; 208 DE_NULL, // VkDescriptorSetLayout* pSetLayouts; 209 0u, // uint32_t pushConstantRangeCount; 210 DE_NULL, // const VkPushConstantRange* pPushConstantRanges; 211 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo; 212 } 213 ); 214 } 215 216 if (m_useMeshShaders) 217 { 218 const auto& mesh = binaries.get("mesh"); 219 const auto& task = binaries.get("task"); 220 if (m_context.getMeshShaderFeaturesEXT().meshShader) 221 { 222 shaderCreateInfos.push_back( 223 { 224 vk::VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT, // VkStructureType sType; 225 DE_NULL, // const void* pNext; 226 0u, // VkShaderCreateFlagsEXT flags; 227 vk::VK_SHADER_STAGE_MESH_BIT_EXT, // VkShaderStageFlagBits stage; 228 0u, // VkShaderStageFlags nextStage; 229 vk::VK_SHADER_CODE_TYPE_SPIRV_EXT, // VkShaderCodeTypeEXT codeType; 230 mesh.getSize(), // size_t codeSize; 231 mesh.getBinary(), // const void* pCode; 232 "main", // const char* pName; 233 0u, // uint32_t setLayoutCount; 234 DE_NULL, // VkDescriptorSetLayout* pSetLayouts; 235 0u, // uint32_t pushConstantRangeCount; 236 DE_NULL, // const VkPushConstantRange* pPushConstantRanges; 237 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo; 238 } 239 ); 240 } 241 242 if (m_context.getMeshShaderFeaturesEXT().taskShader) 243 { 244 shaderCreateInfos.push_back( 245 { 246 vk::VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT, // VkStructureType sType; 247 DE_NULL, // const void* pNext; 248 0u, // VkShaderCreateFlagsEXT flags; 249 vk::VK_SHADER_STAGE_TASK_BIT_EXT, // VkShaderStageFlagBits stage; 250 0u, // VkShaderStageFlags nextStage; 251 vk::VK_SHADER_CODE_TYPE_SPIRV_EXT, // VkShaderCodeTypeEXT codeType; 252 task.getSize(), // size_t codeSize; 253 task.getBinary(), // const void* pCode; 254 "main", // const char* pName; 255 0u, // uint32_t setLayoutCount; 256 DE_NULL, // VkDescriptorSetLayout* pSetLayouts; 257 0u, // uint32_t pushConstantRangeCount; 258 DE_NULL, // const VkPushConstantRange* pPushConstantRanges; 259 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo; 260 } 261 ); 262 } 263 } 264 265 std::vector<vk::VkShaderEXT> shadersSeparate (shaderCreateInfos.size()); 266 std::vector<vk::VkShaderEXT> shadersTogether (shaderCreateInfos.size()); 267 for (deUint32 i = 0; i < (deUint32)shaderCreateInfos.size(); ++i) 268 { 269 vk.createShadersEXT(device, 1, &shaderCreateInfos[i], DE_NULL, &shadersSeparate[i]); 270 } 271 vk.createShadersEXT(device, (deUint32)shaderCreateInfos.size(), &shaderCreateInfos[0], DE_NULL, &shadersTogether[0]); 272 273 bool match = true; 274 for (deUint32 i = 0; i < (deUint32)shaderCreateInfos.size(); ++i) 275 { 276 size_t dataSizeSeparate = 0; 277 size_t dataSizeTogether = 0; 278 vk.getShaderBinaryDataEXT(device, shadersSeparate[i], &dataSizeSeparate, DE_NULL); 279 vk.getShaderBinaryDataEXT(device, shadersTogether[i], &dataSizeTogether, DE_NULL); 280 if (dataSizeSeparate != dataSizeTogether) 281 { 282 log << tcu::TestLog::Message << "Data size of shader created separately is " << dataSizeSeparate << ", but data size of shader created in the same call with others is " << dataSizeTogether << tcu::TestLog::EndMessage; 283 match = false; 284 break; 285 } 286 std::vector<deUint8> dataSeparate(dataSizeSeparate); 287 std::vector<deUint8> dataTogether(dataSizeTogether); 288 vk.getShaderBinaryDataEXT(device, shadersSeparate[i], &dataSizeSeparate, &dataSeparate[0]); 289 vk.getShaderBinaryDataEXT(device, shadersTogether[i], &dataSizeTogether, &dataTogether[0]); 290 for (deUint32 j = 0; j < dataSizeSeparate; ++j) 291 { 292 if (dataSeparate[j] != dataTogether[j]) 293 { 294 log << tcu::TestLog::Message << "Data of shader created separately and data of shader created in the same call with others does not match at index " << j << tcu::TestLog::EndMessage; 295 match = false; 296 break; 297 } 298 } 299 if (!match) 300 break; 301 } 302 303 for (const auto& shader : shadersSeparate) 304 vk.destroyShaderEXT(device, shader, DE_NULL); 305 for (const auto& shader : shadersTogether) 306 vk.destroyShaderEXT(device, shader, DE_NULL); 307 308 if (!match) 309 return tcu::TestStatus::fail("Fail"); 310 311 return tcu::TestStatus::pass("Pass"); 312} 313 314class ShaderObjectCreateCase : public vkt::TestCase 315{ 316public: 317 ShaderObjectCreateCase (tcu::TestContext& testCtx, const std::string& name, const bool useMeshShaders) 318 : vkt::TestCase (testCtx, name) 319 , m_useMeshShaders (useMeshShaders) 320 {} 321 virtual ~ShaderObjectCreateCase (void) {} 322 323 void checkSupport (vkt::Context& context) const override; 324 virtual void initPrograms (vk::SourceCollections& programCollection) const override; 325 TestInstance* createInstance (Context& context) const override { return new ShaderObjectCreateInstance(context, m_useMeshShaders); } 326private: 327 bool m_useMeshShaders; 328}; 329 330void ShaderObjectCreateCase::checkSupport(Context& context) const 331{ 332 context.requireDeviceFunctionality("VK_EXT_shader_object"); 333} 334 335void ShaderObjectCreateCase::initPrograms(vk::SourceCollections& programCollection) const 336{ 337 std::stringstream vert; 338 std::stringstream geom; 339 std::stringstream tesc; 340 std::stringstream tese; 341 std::stringstream frag; 342 std::stringstream comp; 343 std::stringstream mesh; 344 std::stringstream task; 345 346 vert 347 << "#version 450\n" 348 << "layout (location=0) in vec2 inPos;\n" 349 << "void main() {\n" 350 << " vec2 pos = vec2(float(gl_VertexIndex & 1), float((gl_VertexIndex >> 1) & 1));\n" 351 << " gl_Position = vec4(pos, 0.0f, 1.0f);\n" 352 << "}\n"; 353 354 tesc 355 << "#version 450\n" 356 << "\n" 357 << "layout(vertices = 3) out;\n" 358 << "\n" 359 << "void main (void)\n" 360 << "{\n" 361 << " gl_TessLevelInner[0] = 5.0;\n" 362 << " gl_TessLevelInner[1] = 5.0;\n" 363 << "\n" 364 << " gl_TessLevelOuter[0] = 5.0;\n" 365 << " gl_TessLevelOuter[1] = 5.0;\n" 366 << " gl_TessLevelOuter[2] = 5.0;\n" 367 << " gl_TessLevelOuter[3] = 5.0;\n" 368 << "}\n"; 369 370 tese 371 << "#version 450\n" 372 << "\n" 373 << "layout(quads) in;\n" 374 << "\n" 375 << "void main (void)\n" 376 << "{\n" 377 << " highp float x = gl_TessCoord.x*2.0 - 1.0;\n" 378 << " highp float y = gl_TessCoord.y*2.0 - 1.0;\n" 379 << " gl_Position = vec4(x, y, 0.0, 1.0);\n" 380 << "}\n"; 381 382 geom 383 << "#version 450\n" 384 << "layout(points) in;\n" 385 << "layout(points, max_vertices = 1) out;\n" 386 << "\n" 387 << "void main(void)\n" 388 << "{\n" 389 << " gl_Position = gl_in[0].gl_Position;\n" 390 << " EmitVertex();\n" 391 << " EndPrimitive();\n" 392 << "}\n"; 393 394 frag 395 << "#version 450\n" 396 << "layout (location=0) out vec4 outColor;\n" 397 << "void main() {\n" 398 << " outColor = vec4(1.0f);\n" 399 << "}\n"; 400 401 comp 402 << "#version 450\n" 403 << "layout(local_size_x=16, local_size_x=1, local_size_x=1) in;\n" 404 << "layout(binding = 0) buffer Output {\n" 405 << " uint values[16];\n" 406 << "} buffer_out;\n\n" 407 << "void main() {\n" 408 << " buffer_out.values[gl_LocalInvocationID.x] = gl_LocalInvocationID.x;\n" 409 << "}\n"; 410 411 mesh 412 << "#version 460\n" 413 << "#extension GL_EXT_mesh_shader : require\n" 414 << "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" 415 << "layout(max_vertices = 3) out;\n" 416 << "layout(max_primitives = 1) out;\n" 417 << "layout(triangles) out;\n" 418 << "void main() {\n" 419 << " SetMeshOutputsEXT(3,1);\n" 420 << " gl_MeshVerticesEXT[0].gl_Position = vec4(-1.0, -1.0, 0, 1);\n" 421 << " gl_MeshVerticesEXT[1].gl_Position = vec4( 1.0, -1.0, 0, 1);\n" 422 << " gl_MeshVerticesEXT[2].gl_Position = vec4( 0.0, 1.0, 0, 1);\n" 423 << " gl_PrimitiveTriangleIndicesEXT[0] = uvec3(0,1,2);\n" 424 << "}\n"; 425 426 task 427 << "#version 450\n" 428 << "#extension GL_EXT_mesh_shader : enable\n" 429 << "layout (local_size_x=1, local_size_y=1, local_size_z=1) in;\n" 430 << "struct TaskData {\n" 431 << " int t;\n" 432 << "};\n" 433 << "taskPayloadSharedEXT TaskData td;\n" 434 << "void main ()\n" 435 << "{\n" 436 << " td.t = 1;\n" 437 << " EmitMeshTasksEXT(1u, 1u, 1u);\n" 438 << "}\n"; 439 440 programCollection.glslSources.add("vert") << glu::VertexSource(vert.str()); 441 programCollection.glslSources.add("tesc") << glu::TessellationControlSource(tesc.str()); 442 programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(tese.str()); 443 programCollection.glslSources.add("geom") << glu::GeometrySource(geom.str()); 444 programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str()); 445 programCollection.glslSources.add("comp") << glu::ComputeSource(comp.str()); 446 if (m_useMeshShaders) 447 { 448 programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str()) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true); 449 programCollection.glslSources.add("task") << glu::TaskSource(task.str()) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true); 450 } 451} 452 453class ShaderObjectStageInstance : public vkt::TestInstance 454{ 455public: 456 ShaderObjectStageInstance (Context& context, const vk::VkShaderStageFlagBits stage, const bool fail, const bool useMeshShaders) 457 : vkt::TestInstance (context) 458 , m_stage (stage) 459 , m_fail (fail) 460 , m_useMeshShaders (useMeshShaders) 461 {} 462 463 virtual ~ShaderObjectStageInstance (void) {} 464 465 tcu::TestStatus iterate (void) override; 466private: 467 const vk::VkShaderStageFlagBits m_stage; 468 const bool m_fail; 469 const bool m_useMeshShaders; 470}; 471 472tcu::TestStatus ShaderObjectStageInstance::iterate (void) 473{ 474 const vk::VkInstance instance = m_context.getInstance(); 475 const vk::InstanceDriver instanceDriver (m_context.getPlatformInterface(), instance); 476 const vk::DeviceInterface& vk = m_context.getDeviceInterface(); 477 const vk::VkDevice device = m_context.getDevice(); 478 tcu::TestLog& log = m_context.getTestContext().getLog(); 479 const bool tessellationSupported = m_context.getDeviceFeatures().tessellationShader; 480 const bool geometrySupported = m_context.getDeviceFeatures().geometryShader; 481 482 const auto& binaries = m_context.getBinaryCollection(); 483 484 de::Random random (102030); 485 std::vector<vk::VkShaderStageFlagBits> stages = 486 { 487 vk::VK_SHADER_STAGE_VERTEX_BIT, 488 vk::VK_SHADER_STAGE_FRAGMENT_BIT, 489 vk::VK_SHADER_STAGE_COMPUTE_BIT, 490 }; 491 if (m_context.getDeviceFeatures().tessellationShader) 492 { 493 stages.push_back(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT); 494 stages.push_back(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT); 495 } 496 if (m_context.getDeviceFeatures().geometryShader) 497 { 498 stages.push_back(vk::VK_SHADER_STAGE_GEOMETRY_BIT); 499 } 500 if (m_useMeshShaders) 501 { 502 if (m_context.getMeshShaderFeaturesEXT().meshShader) 503 stages.push_back(vk::VK_SHADER_STAGE_MESH_BIT_EXT); 504 if (m_context.getMeshShaderFeaturesEXT().taskShader) 505 stages.push_back(vk::VK_SHADER_STAGE_TASK_BIT_EXT); 506 } 507 508 const deUint32 count = m_stage == vk::VK_SHADER_STAGE_ALL ? 50 : 10; 509 510 const vk::Unique<vk::VkDescriptorSetLayout> descriptorSetLayout( 511 vk::DescriptorSetLayoutBuilder() 512 .addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT) 513 .build(vk, device)); 514 515 516 std::vector<vk::VkShaderCreateInfoEXT> shaderCreateInfos; 517 518 for (deUint32 i = 0; i < count; ++i) 519 { 520 vk::VkShaderStageFlagBits stage; 521 if (m_stage == vk::VK_SHADER_STAGE_ALL) 522 stage = stages[random.getUint32() % stages.size()]; 523 else 524 stage = m_stage; 525 526 bool useLayout = stage == vk::VK_SHADER_STAGE_COMPUTE_BIT; 527 528 const auto& src = binaries.get(getShaderName(stage) + std::to_string(i % 10)); 529 shaderCreateInfos.push_back( 530 { 531 vk::VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT, // VkStructureType sType; 532 DE_NULL, // const void* pNext; 533 0u, // VkShaderCreateFlagsEXT flags; 534 stage, // VkShaderStageFlagBits stage; 535 vk::getShaderObjectNextStages(stage, tessellationSupported, geometrySupported), // VkShaderStageFlags nextStage; 536 vk::VK_SHADER_CODE_TYPE_SPIRV_EXT, // VkShaderCodeTypeEXT codeType; 537 src.getSize(), // size_t codeSize; 538 src.getBinary(), // const void* pCode; 539 "main", // const char* pName; 540 useLayout ? 1u : 0u, // uint32_t setLayoutCount; 541 useLayout ? &*descriptorSetLayout : DE_NULL, // VkDescriptorSetLayout* pSetLayouts; 542 0u, // uint32_t pushConstantRangeCount; 543 DE_NULL, // const VkPushConstantRange* pPushConstantRanges; 544 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo; 545 }); 546 } 547 548 std::vector<vk::VkShaderEXT> shaders (count, VK_NULL_HANDLE); 549 vk::VkResult result; 550 result = vk.createShadersEXT(device, count, &shaderCreateInfos[0], DE_NULL, &shaders[0]); 551 if (result != vk::VK_SUCCESS) 552 { 553 log << tcu::TestLog::Message << "vkCreateShadersEXT returned " << result << tcu::TestLog::EndMessage; 554 return tcu::TestStatus::fail("Fail"); 555 } 556 557 std::vector<size_t> binarySizes (count); 558 std::vector<std::vector<deUint8>> binaryData (count); 559 for (size_t i = 0; i < count; ++i) 560 { 561 vk.getShaderBinaryDataEXT(device, shaders[i], &binarySizes[i], DE_NULL); 562 binaryData[i].resize(binarySizes[i]); 563 vk.getShaderBinaryDataEXT(device, shaders[i], &binarySizes[i], (void*)&binaryData[i][0]); 564 } 565 566 for (const auto& shader : shaders) 567 vk.destroyShaderEXT(device, shader, DE_NULL); 568 569 const deUint32 failIndex = random.getUint32() % count; 570 571 for (deUint32 i = 0; i < count; ++i) 572 { 573 shaderCreateInfos[i].codeType = vk::VK_SHADER_CODE_TYPE_BINARY_EXT; 574 if (m_fail && failIndex == i) 575 shaderCreateInfos[i].codeSize = 1; 576 else 577 shaderCreateInfos[i].codeSize = binarySizes[i]; 578 shaderCreateInfos[i].pCode = &binaryData[i][0]; 579 } 580 581 deUint32 garbage = 1234u; 582 std::vector<vk::VkShaderEXT> binaryShaders (count, garbage); // Fill with garbage 583 result = vk.createShadersEXT(device, count, &shaderCreateInfos[0], DE_NULL, &binaryShaders[0]); 584 585 if (m_fail) 586 { 587 if (result != vk::VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT) 588 { 589 log << tcu::TestLog::Message << "Shader at index " << failIndex << "was created with size 0, but vkCreateShadersEXT returned " << result << tcu::TestLog::EndMessage; 590 return tcu::TestStatus::fail("Fail"); 591 } 592 593 for (deUint32 i = 0; i < failIndex; ++i) 594 { 595 if (binaryShaders[i] == garbage) 596 { 597 log << tcu::TestLog::Message << "vkCreateShadersEXT returned VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT and failed at index " << failIndex << ", but shader at index " << i << "was not created" << tcu::TestLog::EndMessage; 598 return tcu::TestStatus::fail("Fail"); 599 } 600 vk.destroyShaderEXT(device, binaryShaders[i], DE_NULL); 601 } 602 if (binaryShaders[failIndex] != VK_NULL_HANDLE) 603 { 604 log << tcu::TestLog::Message << "vkCreateShadersEXT returned VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT, creating shader at index " << failIndex << " failed, but the shader is not VK_NULL_HANDLE" << tcu::TestLog::EndMessage; 605 return tcu::TestStatus::fail("Fail"); 606 } 607 } 608 else 609 { 610 if (result != vk::VK_SUCCESS) 611 { 612 log << tcu::TestLog::Message << "vkCreateShadersEXT returned " << result << tcu::TestLog::EndMessage; 613 return tcu::TestStatus::fail("Fail"); 614 } 615 616 for (const auto& shader : binaryShaders) 617 vk.destroyShaderEXT(device, shader, DE_NULL); 618 } 619 620 return tcu::TestStatus::pass("Pass"); 621} 622 623class ShaderObjectStageCase : public vkt::TestCase 624{ 625public: 626 ShaderObjectStageCase (tcu::TestContext& testCtx, const std::string& name, const vk::VkShaderStageFlagBits stage, const bool fail, const bool useMeshShaders) 627 : vkt::TestCase (testCtx, name) 628 , m_stage (stage) 629 , m_fail (fail) 630 , m_useMeshShaders (useMeshShaders) 631 {} 632 virtual ~ShaderObjectStageCase (void) {} 633 634 void checkSupport (vkt::Context& context) const override; 635 virtual void initPrograms (vk::SourceCollections& programCollection) const override; 636 TestInstance* createInstance (Context& context) const override { return new ShaderObjectStageInstance(context, m_stage, m_fail, m_useMeshShaders); } 637private: 638 const vk::VkShaderStageFlagBits m_stage; 639 const bool m_fail; 640 const bool m_useMeshShaders; 641}; 642 643void ShaderObjectStageCase::checkSupport (Context& context) const 644{ 645 context.requireDeviceFunctionality("VK_EXT_shader_object"); 646 if (m_useMeshShaders) 647 context.requireDeviceFunctionality("VK_EXT_mesh_shader"); 648 649 if (m_stage == vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT || m_stage == vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) 650 context.requireDeviceCoreFeature(vkt::DEVICE_CORE_FEATURE_TESSELLATION_SHADER); 651 if (m_stage == vk::VK_SHADER_STAGE_GEOMETRY_BIT) 652 context.requireDeviceCoreFeature(vkt::DEVICE_CORE_FEATURE_GEOMETRY_SHADER); 653 if (m_stage == vk::VK_SHADER_STAGE_TASK_BIT_EXT && context.getMeshShaderFeaturesEXT().taskShader == VK_FALSE) 654 TCU_THROW(NotSupportedError, "Task shaders not supported"); 655 if (m_stage == vk::VK_SHADER_STAGE_MESH_BIT_EXT && context.getMeshShaderFeaturesEXT().meshShader == VK_FALSE) 656 TCU_THROW(NotSupportedError, "Mesh shaders not supported"); 657} 658 659void ShaderObjectStageCase::initPrograms (vk::SourceCollections& programCollection) const 660{ 661 for (deUint32 i = 0; i < 10; ++i) 662 { 663 std::stringstream vert; 664 std::stringstream geom; 665 std::stringstream tesc; 666 std::stringstream tese; 667 std::stringstream frag; 668 std::stringstream comp; 669 std::stringstream mesh; 670 std::stringstream task; 671 672 vert 673 << "#version 450\n" 674 << "layout (location=0) in vec2 inPos;\n" 675 << "void main() {\n" 676 << " vec2 pos = vec2(float(gl_VertexIndex & 1), float((gl_VertexIndex >> 1) & 1));\n" 677 << " gl_Position = vec4(pos * float(" << i << "), 0.0f, 1.0f);\n" 678 << "}\n"; 679 680 tesc 681 << "#version 450\n" 682 << "\n" 683 << "layout(vertices = 3) out;\n" 684 << "\n" 685 << "void main (void)\n" 686 << "{\n" 687 << " gl_TessLevelInner[0] = 5.0 + float(" << i << ");\n" 688 << " gl_TessLevelInner[1] = 5.0 + float(" << i << ");\n" 689 << "\n" 690 << " gl_TessLevelOuter[0] = 5.0;\n" 691 << " gl_TessLevelOuter[1] = 5.0;\n" 692 << " gl_TessLevelOuter[2] = 5.0;\n" 693 << " gl_TessLevelOuter[3] = 5.0;\n" 694 << "}\n"; 695 696 tese 697 << "#version 450\n" 698 << "\n" 699 << "layout(quads) in;\n" 700 << "\n" 701 << "void main (void)\n" 702 << "{\n" 703 << " highp float x = gl_TessCoord.x * float(" << i << ") - 1.0;\n" 704 << " highp float y = gl_TessCoord.y * float(" << i << ") - 1.0;\n" 705 << " gl_Position = vec4(x, y, 0.0, 1.0);\n" 706 << "}\n"; 707 708 geom 709 << "#version 450\n" 710 << "layout(points) in;\n" 711 << "layout(points, max_vertices = 1) out;\n" 712 << "\n" 713 << "void main(void)\n" 714 << "{\n" 715 << " gl_Position = gl_in[0].gl_Position;\n" 716 << " gl_Position.xy += vec2(float(" << i << "));\n" 717 << " EmitVertex();\n" 718 << " EndPrimitive();\n" 719 << "}\n"; 720 721 frag 722 << "#version 450\n" 723 << "layout (location=0) out vec4 outColor;\n" 724 << "void main() {\n" 725 << " outColor = vec4(1.0f / (1.0f + float(" << i << ")));\n" 726 << "}\n"; 727 728 comp 729 << "#version 450\n" 730 << "layout(local_size_x=16, local_size_x=1, local_size_x=1) in;\n" 731 << "layout(binding = 0) buffer Output {\n" 732 << " uint values[16];\n" 733 << "} buffer_out;\n\n" 734 << "void main() {\n" 735 << " buffer_out.values[gl_LocalInvocationID.x] = gl_LocalInvocationID.x + " << i << ";\n" 736 << "}\n"; 737 738 mesh 739 << "#version 460\n" 740 << "#extension GL_EXT_mesh_shader : require\n" 741 << "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" 742 << "layout(max_vertices = 3) out;\n" 743 << "layout(max_primitives = 1) out;\n" 744 << "layout(triangles) out;\n" 745 << "void main() {\n" 746 << " SetMeshOutputsEXT(3,1);\n" 747 << " gl_MeshVerticesEXT[0].gl_Position = vec4(-1.0, -1.0, 0, 1);\n" 748 << " gl_MeshVerticesEXT[1].gl_Position = vec4( 1.0, -1.0, 0, 1);\n" 749 << " gl_MeshVerticesEXT[2].gl_Position = vec4( 0.0, 1.0, 0, 1);\n" 750 << " gl_PrimitiveTriangleIndicesEXT[0] = uvec3(0,1,2);\n" 751 << "}\n"; 752 753 task 754 << "#version 450\n" 755 << "#extension GL_EXT_mesh_shader : enable\n" 756 << "layout (local_size_x=1, local_size_y=1, local_size_z=1) in;\n" 757 << "struct TaskData {\n" 758 << " int t;\n" 759 << "};\n" 760 << "taskPayloadSharedEXT TaskData td;\n" 761 << "void main ()\n" 762 << "{\n" 763 << " td.t = 1;\n" 764 << " EmitMeshTasksEXT(1u, 1u, 1u);\n" 765 << "}\n"; 766 767 programCollection.glslSources.add("vert" + std::to_string(i)) << glu::VertexSource(vert.str()); 768 programCollection.glslSources.add("tesc" + std::to_string(i)) << glu::TessellationControlSource(tesc.str()); 769 programCollection.glslSources.add("tese" + std::to_string(i)) << glu::TessellationEvaluationSource(tese.str()); 770 programCollection.glslSources.add("geom" + std::to_string(i)) << glu::GeometrySource(geom.str()); 771 programCollection.glslSources.add("frag" + std::to_string(i)) << glu::FragmentSource(frag.str()); 772 programCollection.glslSources.add("comp" + std::to_string(i)) << glu::ComputeSource(comp.str()); 773 if (m_useMeshShaders) 774 { 775 programCollection.glslSources.add("mesh" + std::to_string(i)) << glu::MeshSource(mesh.str()) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true); 776 programCollection.glslSources.add("task" + std::to_string(i)) << glu::TaskSource(task.str()) << vk::ShaderBuildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true); 777 } 778 } 779} 780 781} 782 783tcu::TestCaseGroup* createShaderObjectCreateTests (tcu::TestContext& testCtx) 784{ 785 de::MovePtr<tcu::TestCaseGroup> createGroup(new tcu::TestCaseGroup(testCtx, "create")); 786 787 de::MovePtr<tcu::TestCaseGroup> multipleGroup(new tcu::TestCaseGroup(testCtx, "multiple")); 788 789 multipleGroup->addChild(new ShaderObjectCreateCase(testCtx, "all", false)); 790 multipleGroup->addChild(new ShaderObjectCreateCase(testCtx, "all_with_mesh", true)); 791 792 createGroup->addChild(multipleGroup.release()); 793 794 const struct 795 { 796 vk::VkShaderStageFlagBits stage; 797 const bool useMeshShaders; 798 const char* name; 799 } stageTests[] = 800 { 801 { vk::VK_SHADER_STAGE_VERTEX_BIT, false, "vert" }, 802 { vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, false, "tesc" }, 803 { vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, false, "tese" }, 804 { vk::VK_SHADER_STAGE_GEOMETRY_BIT, false, "geom" }, 805 { vk::VK_SHADER_STAGE_FRAGMENT_BIT, false, "frag" }, 806 { vk::VK_SHADER_STAGE_COMPUTE_BIT, false, "comp" }, 807 { vk::VK_SHADER_STAGE_MESH_BIT_EXT, true, "mesh" }, 808 { vk::VK_SHADER_STAGE_TASK_BIT_EXT, true, "task" }, 809 { vk::VK_SHADER_STAGE_ALL, false, "all" }, 810 { vk::VK_SHADER_STAGE_ALL, true, "all_with_mesh" }, 811 }; 812 813 const struct 814 { 815 bool fail; 816 const char* name; 817 } failTests[] = 818 { 819 { false, "succeed" }, 820 { true, "fail" }, 821 }; 822 823 for (const auto& stage : stageTests) 824 { 825 de::MovePtr<tcu::TestCaseGroup> stageGroup(new tcu::TestCaseGroup(testCtx, stage.name)); 826 for (const auto& failTest : failTests) 827 { 828 stageGroup->addChild(new ShaderObjectStageCase(testCtx, failTest.name, stage.stage, failTest.fail, stage.useMeshShaders)); 829 } 830 createGroup->addChild(stageGroup.release()); 831 } 832 833 return createGroup.release(); 834} 835 836} // ShaderObject 837} // vkt 838