1 /*------------------------------------------------------------------------- 2 * Vulkan Conformance Tests 3 * ------------------------ 4 * 5 * Copyright (c) 2015 Google Inc. 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 *//*! 20 * \file 21 * \brief Binding shader access tests 22 *//*--------------------------------------------------------------------*/ 23 24 #include "vktBindingShaderAccessTests.hpp" 25 26 #include "vktTestCase.hpp" 27 28 #include "vkDefs.hpp" 29 #include "vkRef.hpp" 30 #include "vkRefUtil.hpp" 31 #include "vkPlatform.hpp" 32 #include "vkPrograms.hpp" 33 #include "vkMemUtil.hpp" 34 #include "vkBuilderUtil.hpp" 35 #include "vkQueryUtil.hpp" 36 #include "vkImageUtil.hpp" 37 #include "vkTypeUtil.hpp" 38 39 #include "tcuVector.hpp" 40 #include "tcuVectorUtil.hpp" 41 #include "tcuTexture.hpp" 42 #include "tcuTextureUtil.hpp" 43 #include "tcuResultCollector.hpp" 44 #include "tcuTestLog.hpp" 45 #include "tcuRGBA.hpp" 46 #include "tcuSurface.hpp" 47 #include "tcuImageCompare.hpp" 48 49 #include "deUniquePtr.hpp" 50 #include "deSharedPtr.hpp" 51 #include "deStringUtil.hpp" 52 #include "deArrayUtil.hpp" 53 54 #include "qpInfo.h" 55 #include <iostream> 56 57 namespace vkt 58 { 59 namespace BindingModel 60 { 61 namespace 62 { 63 64 enum ResourceFlag 65 { 66 RESOURCE_FLAG_IMMUTABLE_SAMPLER = (1u << 0u), 67 68 RESOURCE_FLAG_LAST = (1u << 1u) 69 }; 70 71 enum DescriptorUpdateMethod 72 { 73 DESCRIPTOR_UPDATE_METHOD_NORMAL = 0, //!< use vkUpdateDescriptorSets 74 DESCRIPTOR_UPDATE_METHOD_WITH_TEMPLATE, //!< use descriptor update templates 75 DESCRIPTOR_UPDATE_METHOD_WITH_PUSH, //!< use push descriptor updates 76 DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE, //!< use push descriptor update templates 77 78 DESCRIPTOR_UPDATE_METHOD_LAST 79 }; 80 81 std::string stringifyDescriptorUpdateMethod(DescriptorUpdateMethod method) 82 { 83 switch (method) 84 { 85 case DESCRIPTOR_UPDATE_METHOD_NORMAL: 86 return ""; 87 break; 88 89 case DESCRIPTOR_UPDATE_METHOD_WITH_TEMPLATE: 90 return "with_template"; 91 break; 92 93 case DESCRIPTOR_UPDATE_METHOD_WITH_PUSH: 94 return "with_push"; 95 break; 96 97 case DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE: 98 return "with_push_template"; 99 break; 100 101 default: 102 return "N/A"; 103 break; 104 } 105 } 106 107 static const char* const s_quadrantGenVertexPosSource = " highp int quadPhase = gl_VertexIndex % 6;\n" 108 " highp int quadXcoord = int(quadPhase == 1 || quadPhase == 4 || quadPhase == 5);\n" 109 " highp int quadYcoord = int(quadPhase == 2 || quadPhase == 3 || quadPhase == 5);\n" 110 " highp int quadOriginX = (gl_VertexIndex / 6) % 2;\n" 111 " highp int quadOriginY = (gl_VertexIndex / 6) / 2;\n" 112 " quadrant_id = gl_VertexIndex / 6;\n" 113 " result_position = vec4(float(quadOriginX + quadXcoord - 1), float(quadOriginY + quadYcoord - 1), 0.0, 1.0);\n"; 114 115 std::string genPerVertexBlock (const vk::VkShaderStageFlagBits stage, const glu::GLSLVersion version) 116 { 117 static const char* const block = "gl_PerVertex {\n" 118 " vec4 gl_Position;\n" 119 " float gl_PointSize;\n" // not used, but for compatibility with how implicit block is declared in ES 120 "}"; 121 std::ostringstream str; 122 123 if (!glu::glslVersionIsES(version)) 124 switch (stage) 125 { 126 case vk::VK_SHADER_STAGE_VERTEX_BIT: 127 str << "out " << block << ";\n"; 128 break; 129 130 case vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT: 131 str << "in " << block << " gl_in[gl_MaxPatchVertices];\n" 132 << "out " << block << " gl_out[];\n"; 133 break; 134 135 case vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT: 136 str << "in " << block << " gl_in[gl_MaxPatchVertices];\n" 137 << "out " << block << ";\n"; 138 break; 139 140 case vk::VK_SHADER_STAGE_GEOMETRY_BIT: 141 str << "in " << block << " gl_in[];\n" 142 << "out " << block << ";\n"; 143 break; 144 145 default: 146 break; 147 } 148 149 return str.str(); 150 } 151 152 bool isUniformDescriptorType (vk::VkDescriptorType type) 153 { 154 return type == vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER || 155 type == vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC || 156 type == vk::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; 157 } 158 159 bool isDynamicDescriptorType (vk::VkDescriptorType type) 160 { 161 return type == vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC || type == vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC; 162 } 163 164 void verifyDriverSupport(const vk::VkPhysicalDeviceFeatures& deviceFeatures, 165 const std::vector<std::string>& deviceExtensions, 166 DescriptorUpdateMethod updateMethod, 167 vk::VkDescriptorType descType, 168 vk::VkShaderStageFlags activeStages) 169 { 170 std::vector<std::string> extensionNames; 171 size_t numExtensionsNeeded = 0; 172 173 switch (updateMethod) 174 { 175 case DESCRIPTOR_UPDATE_METHOD_WITH_PUSH: 176 extensionNames.push_back("VK_KHR_push_descriptor"); 177 break; 178 179 // fall through 180 case DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE: 181 extensionNames.push_back("VK_KHR_push_descriptor"); 182 case DESCRIPTOR_UPDATE_METHOD_WITH_TEMPLATE: 183 extensionNames.push_back("VK_KHR_descriptor_update_template"); 184 break; 185 186 case DESCRIPTOR_UPDATE_METHOD_NORMAL: 187 // no extensions needed 188 break; 189 190 default: 191 DE_FATAL("Impossible"); 192 } 193 194 numExtensionsNeeded = extensionNames.size(); 195 196 if (numExtensionsNeeded > 0) 197 { 198 for (size_t deviceExtNdx = 0; deviceExtNdx < deviceExtensions.size(); deviceExtNdx++) 199 { 200 for (size_t requiredExtNdx = 0; requiredExtNdx < extensionNames.size(); requiredExtNdx++) 201 { 202 if (deStringEqual(deviceExtensions[deviceExtNdx].c_str(), extensionNames[requiredExtNdx].c_str())) 203 { 204 --numExtensionsNeeded; 205 break; 206 } 207 } 208 209 if (numExtensionsNeeded == 0) 210 break; 211 } 212 213 if (numExtensionsNeeded > 0) 214 { 215 TCU_THROW(NotSupportedError, (stringifyDescriptorUpdateMethod(updateMethod) + " tests are not supported").c_str()); 216 } 217 } 218 219 switch (descType) 220 { 221 case vk::VK_DESCRIPTOR_TYPE_SAMPLER: 222 case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: 223 case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: 224 case vk::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: 225 case vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: 226 case vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: 227 // These are supported in all stages 228 return; 229 230 case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: 231 case vk::VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: 232 case vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: 233 case vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: 234 if (activeStages & (vk::VK_SHADER_STAGE_VERTEX_BIT | 235 vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | 236 vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT | 237 vk::VK_SHADER_STAGE_GEOMETRY_BIT)) 238 { 239 if (!deviceFeatures.vertexPipelineStoresAndAtomics) 240 TCU_THROW(NotSupportedError, (de::toString(descType) + " is not supported in the vertex pipeline").c_str()); 241 } 242 243 if (activeStages & vk::VK_SHADER_STAGE_FRAGMENT_BIT) 244 { 245 if (!deviceFeatures.fragmentStoresAndAtomics) 246 TCU_THROW(NotSupportedError, (de::toString(descType) + " is not supported in fragment shaders").c_str()); 247 } 248 return; 249 250 default: 251 DE_FATAL("Impossible"); 252 } 253 } 254 255 vk::VkImageType viewTypeToImageType (vk::VkImageViewType type) 256 { 257 switch (type) 258 { 259 case vk::VK_IMAGE_VIEW_TYPE_1D: 260 case vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY: return vk::VK_IMAGE_TYPE_1D; 261 case vk::VK_IMAGE_VIEW_TYPE_2D: 262 case vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY: return vk::VK_IMAGE_TYPE_2D; 263 case vk::VK_IMAGE_VIEW_TYPE_3D: return vk::VK_IMAGE_TYPE_3D; 264 case vk::VK_IMAGE_VIEW_TYPE_CUBE: 265 case vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY: return vk::VK_IMAGE_TYPE_2D; 266 267 default: 268 DE_FATAL("Impossible"); 269 return (vk::VkImageType)0; 270 } 271 } 272 273 vk::VkImageLayout getImageLayoutForDescriptorType (vk::VkDescriptorType descType) 274 { 275 if (descType == vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) 276 return vk::VK_IMAGE_LAYOUT_GENERAL; 277 else 278 return vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; 279 } 280 281 deUint32 getTextureLevelPyramidDataSize (const tcu::TextureLevelPyramid& srcImage) 282 { 283 deUint32 dataSize = 0; 284 for (int level = 0; level < srcImage.getNumLevels(); ++level) 285 { 286 const tcu::ConstPixelBufferAccess srcAccess = srcImage.getLevel(level); 287 288 // tightly packed 289 DE_ASSERT(srcAccess.getFormat().getPixelSize() == srcAccess.getPixelPitch()); 290 291 dataSize += srcAccess.getWidth() * srcAccess.getHeight() * srcAccess.getDepth() * srcAccess.getFormat().getPixelSize(); 292 } 293 return dataSize; 294 } 295 296 void writeTextureLevelPyramidData (void* dst, deUint32 dstLen, const tcu::TextureLevelPyramid& srcImage, vk::VkImageViewType viewType, std::vector<vk::VkBufferImageCopy>* copySlices) 297 { 298 // \note cube is copied face-by-face 299 const deUint32 arraySize = (viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ? (srcImage.getLevel(0).getHeight()) : 300 (viewType == vk::VK_IMAGE_VIEW_TYPE_2D || viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY) ? (srcImage.getLevel(0).getDepth()) : 301 (viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? (1) : 302 (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ? (srcImage.getLevel(0).getDepth()) : 303 ((deUint32)0); 304 deUint32 levelOffset = 0; 305 306 DE_ASSERT(arraySize != 0); 307 308 for (int level = 0; level < srcImage.getNumLevels(); ++level) 309 { 310 const tcu::ConstPixelBufferAccess srcAccess = srcImage.getLevel(level); 311 const tcu::PixelBufferAccess dstAccess (srcAccess.getFormat(), srcAccess.getSize(), srcAccess.getPitch(), (deUint8*)dst + levelOffset); 312 const deUint32 dataSize = srcAccess.getWidth() * srcAccess.getHeight() * srcAccess.getDepth() * srcAccess.getFormat().getPixelSize(); 313 const deUint32 sliceDataSize = dataSize / arraySize; 314 const deInt32 sliceHeight = (viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ? (1) : (srcAccess.getHeight()); 315 const deInt32 sliceDepth = (viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? (srcAccess.getDepth()) : (1); 316 const tcu::IVec3 sliceSize (srcAccess.getWidth(), sliceHeight, sliceDepth); 317 318 // tightly packed 319 DE_ASSERT(srcAccess.getFormat().getPixelSize() == srcAccess.getPixelPitch()); 320 321 for (int sliceNdx = 0; sliceNdx < (int)arraySize; ++sliceNdx) 322 { 323 const vk::VkBufferImageCopy copySlice = 324 { 325 (vk::VkDeviceSize)levelOffset + sliceNdx * sliceDataSize, // bufferOffset 326 (deUint32)sliceSize.x(), // bufferRowLength 327 (deUint32)sliceSize.y(), // bufferImageHeight 328 { 329 vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask 330 (deUint32)level, // mipLevel 331 (deUint32)sliceNdx, // arrayLayer 332 1u, // arraySize 333 }, // imageSubresource 334 { 335 0, 336 0, 337 0, 338 }, // imageOffset 339 { 340 (deUint32)sliceSize.x(), 341 (deUint32)sliceSize.y(), 342 (deUint32)sliceSize.z(), 343 } // imageExtent 344 }; 345 copySlices->push_back(copySlice); 346 } 347 348 DE_ASSERT(arraySize * sliceDataSize == dataSize); 349 350 tcu::copy(dstAccess, srcAccess); 351 levelOffset += dataSize; 352 } 353 354 DE_ASSERT(dstLen == levelOffset); 355 DE_UNREF(dstLen); 356 } 357 358 de::MovePtr<vk::Allocation> allocateAndBindObjectMemory (const vk::DeviceInterface& vki, vk::VkDevice device, vk::Allocator& allocator, vk::VkBuffer buffer, vk::MemoryRequirement requirement) 359 { 360 const vk::VkMemoryRequirements requirements = vk::getBufferMemoryRequirements(vki, device, buffer); 361 de::MovePtr<vk::Allocation> allocation = allocator.allocate(requirements, requirement); 362 363 VK_CHECK(vki.bindBufferMemory(device, buffer, allocation->getMemory(), allocation->getOffset())); 364 return allocation; 365 } 366 367 de::MovePtr<vk::Allocation> allocateAndBindObjectMemory (const vk::DeviceInterface& vki, vk::VkDevice device, vk::Allocator& allocator, vk::VkImage image, vk::MemoryRequirement requirement) 368 { 369 const vk::VkMemoryRequirements requirements = vk::getImageMemoryRequirements(vki, device, image); 370 de::MovePtr<vk::Allocation> allocation = allocator.allocate(requirements, requirement); 371 372 VK_CHECK(vki.bindImageMemory(device, image, allocation->getMemory(), allocation->getOffset())); 373 return allocation; 374 } 375 376 vk::VkDescriptorImageInfo makeDescriptorImageInfo (vk::VkSampler sampler) 377 { 378 return vk::makeDescriptorImageInfo(sampler, (vk::VkImageView)0, (vk::VkImageLayout)0); 379 } 380 381 vk::VkDescriptorImageInfo makeDescriptorImageInfo (vk::VkImageView imageView, vk::VkImageLayout layout) 382 { 383 return vk::makeDescriptorImageInfo((vk::VkSampler)0, imageView, layout); 384 } 385 386 void drawQuadrantReferenceResult (const tcu::PixelBufferAccess& dst, const tcu::Vec4& c1, const tcu::Vec4& c2, const tcu::Vec4& c3, const tcu::Vec4& c4) 387 { 388 tcu::clear(tcu::getSubregion(dst, 0, 0, dst.getWidth() / 2, dst.getHeight() / 2), c1); 389 tcu::clear(tcu::getSubregion(dst, dst.getWidth() / 2, 0, dst.getWidth() - dst.getWidth() / 2, dst.getHeight() / 2), c2); 390 tcu::clear(tcu::getSubregion(dst, 0, dst.getHeight() / 2, dst.getWidth() / 2, dst.getHeight() - dst.getHeight() / 2), c3); 391 tcu::clear(tcu::getSubregion(dst, dst.getWidth() / 2, dst.getHeight() / 2, dst.getWidth() - dst.getWidth() / 2, dst.getHeight() - dst.getHeight() / 2), c4); 392 } 393 394 static const vk::VkDescriptorUpdateTemplateEntryKHR createTemplateBinding (deUint32 binding, deUint32 arrayElement, deUint32 descriptorCount, vk::VkDescriptorType descriptorType, size_t offset, size_t stride) 395 { 396 const vk::VkDescriptorUpdateTemplateEntryKHR updateBinding = 397 { 398 binding, 399 arrayElement, 400 descriptorCount, 401 descriptorType, 402 offset, 403 stride 404 }; 405 406 return updateBinding; 407 } 408 409 class RawUpdateRegistry 410 { 411 public: 412 RawUpdateRegistry (void); 413 414 template<typename Type> 415 void addWriteObject (const Type& updateObject); 416 size_t getWriteObjectOffset (const deUint32 objectId); 417 const deUint8* getRawPointer () const; 418 419 private: 420 421 std::vector<deUint8> m_updateEntries; 422 std::vector<size_t> m_updateEntryOffsets; 423 size_t m_nextOffset; 424 }; 425 426 RawUpdateRegistry::RawUpdateRegistry (void) 427 : m_updateEntries() 428 , m_updateEntryOffsets() 429 , m_nextOffset(0) 430 { 431 } 432 433 template<typename Type> 434 void RawUpdateRegistry::addWriteObject (const Type& updateObject) 435 { 436 m_updateEntryOffsets.push_back(m_nextOffset); 437 438 // in this case, elements <=> bytes 439 m_updateEntries.resize(m_nextOffset + sizeof(updateObject)); 440 Type* t = reinterpret_cast<Type*>(m_updateEntries.data() + m_nextOffset); 441 *t = updateObject; 442 m_nextOffset += sizeof(updateObject); 443 } 444 445 size_t RawUpdateRegistry::getWriteObjectOffset (const deUint32 objectId) 446 { 447 return m_updateEntryOffsets[objectId]; 448 } 449 450 const deUint8* RawUpdateRegistry::getRawPointer () const 451 { 452 return m_updateEntries.data(); 453 } 454 455 class SingleTargetRenderInstance : public vkt::TestInstance 456 { 457 public: 458 SingleTargetRenderInstance (Context& context, 459 const tcu::UVec2& size); 460 461 private: 462 static vk::Move<vk::VkImage> createColorAttachment (const vk::DeviceInterface& vki, 463 vk::VkDevice device, 464 vk::Allocator& allocator, 465 const tcu::TextureFormat& format, 466 const tcu::UVec2& size, 467 de::MovePtr<vk::Allocation>* outAllocation); 468 469 static vk::Move<vk::VkImageView> createColorAttachmentView (const vk::DeviceInterface& vki, 470 vk::VkDevice device, 471 const tcu::TextureFormat& format, 472 vk::VkImage image); 473 474 static vk::Move<vk::VkRenderPass> createRenderPass (const vk::DeviceInterface& vki, 475 vk::VkDevice device, 476 const tcu::TextureFormat& format); 477 478 static vk::Move<vk::VkFramebuffer> createFramebuffer (const vk::DeviceInterface& vki, 479 vk::VkDevice device, 480 vk::VkRenderPass renderpass, 481 vk::VkImageView colorAttachmentView, 482 const tcu::UVec2& size); 483 484 static vk::Move<vk::VkCommandPool> createCommandPool (const vk::DeviceInterface& vki, 485 vk::VkDevice device, 486 deUint32 queueFamilyIndex); 487 488 virtual void logTestPlan (void) const = 0; 489 virtual void renderToTarget (void) = 0; 490 virtual tcu::TestStatus verifyResultImage (const tcu::ConstPixelBufferAccess& result) const = 0; 491 492 void readRenderTarget (tcu::TextureLevel& dst); 493 tcu::TestStatus iterate (void); 494 495 protected: 496 const tcu::TextureFormat m_targetFormat; 497 const tcu::UVec2 m_targetSize; 498 499 const vk::DeviceInterface& m_vki; 500 const vk::VkDevice m_device; 501 const vk::VkQueue m_queue; 502 const deUint32 m_queueFamilyIndex; 503 vk::Allocator& m_allocator; 504 de::MovePtr<vk::Allocation> m_colorAttachmentMemory; 505 const vk::Unique<vk::VkImage> m_colorAttachmentImage; 506 const vk::Unique<vk::VkImageView> m_colorAttachmentView; 507 const vk::Unique<vk::VkRenderPass> m_renderPass; 508 const vk::Unique<vk::VkFramebuffer> m_framebuffer; 509 const vk::Unique<vk::VkCommandPool> m_cmdPool; 510 511 bool m_firstIteration; 512 }; 513 514 SingleTargetRenderInstance::SingleTargetRenderInstance (Context& context, 515 const tcu::UVec2& size) 516 : vkt::TestInstance (context) 517 , m_targetFormat (tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8) 518 , m_targetSize (size) 519 , m_vki (context.getDeviceInterface()) 520 , m_device (context.getDevice()) 521 , m_queue (context.getUniversalQueue()) 522 , m_queueFamilyIndex (context.getUniversalQueueFamilyIndex()) 523 , m_allocator (context.getDefaultAllocator()) 524 , m_colorAttachmentMemory (DE_NULL) 525 , m_colorAttachmentImage (createColorAttachment(m_vki, m_device, m_allocator, m_targetFormat, m_targetSize, &m_colorAttachmentMemory)) 526 , m_colorAttachmentView (createColorAttachmentView(m_vki, m_device, m_targetFormat, *m_colorAttachmentImage)) 527 , m_renderPass (createRenderPass(m_vki, m_device, m_targetFormat)) 528 , m_framebuffer (createFramebuffer(m_vki, m_device, *m_renderPass, *m_colorAttachmentView, m_targetSize)) 529 , m_cmdPool (createCommandPool(m_vki, m_device, context.getUniversalQueueFamilyIndex())) 530 , m_firstIteration (true) 531 { 532 } 533 534 vk::Move<vk::VkImage> SingleTargetRenderInstance::createColorAttachment (const vk::DeviceInterface& vki, 535 vk::VkDevice device, 536 vk::Allocator& allocator, 537 const tcu::TextureFormat& format, 538 const tcu::UVec2& size, 539 de::MovePtr<vk::Allocation>* outAllocation) 540 { 541 const vk::VkImageCreateInfo imageInfo = 542 { 543 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, 544 DE_NULL, 545 (vk::VkImageCreateFlags)0, 546 vk::VK_IMAGE_TYPE_2D, // imageType 547 vk::mapTextureFormat(format), // format 548 { size.x(), size.y(), 1u }, // extent 549 1, // mipLevels 550 1, // arraySize 551 vk::VK_SAMPLE_COUNT_1_BIT, // samples 552 vk::VK_IMAGE_TILING_OPTIMAL, // tiling 553 vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // usage 554 vk::VK_SHARING_MODE_EXCLUSIVE, // sharingMode 555 0u, // queueFamilyCount 556 DE_NULL, // pQueueFamilyIndices 557 vk::VK_IMAGE_LAYOUT_UNDEFINED, // initialLayout 558 }; 559 560 vk::Move<vk::VkImage> image (vk::createImage(vki, device, &imageInfo)); 561 de::MovePtr<vk::Allocation> allocation (allocateAndBindObjectMemory(vki, device, allocator, *image, vk::MemoryRequirement::Any)); 562 563 *outAllocation = allocation; 564 return image; 565 } 566 567 vk::Move<vk::VkImageView> SingleTargetRenderInstance::createColorAttachmentView (const vk::DeviceInterface& vki, 568 vk::VkDevice device, 569 const tcu::TextureFormat& format, 570 vk::VkImage image) 571 { 572 const vk::VkImageViewCreateInfo createInfo = 573 { 574 vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, 575 DE_NULL, 576 (vk::VkImageViewCreateFlags)0, 577 image, // image 578 vk::VK_IMAGE_VIEW_TYPE_2D, // viewType 579 vk::mapTextureFormat(format), // format 580 vk::makeComponentMappingRGBA(), 581 { 582 vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask 583 0u, // baseMipLevel 584 1u, // mipLevels 585 0u, // baseArrayLayer 586 1u, // arraySize 587 }, 588 }; 589 590 return vk::createImageView(vki, device, &createInfo); 591 } 592 593 vk::Move<vk::VkRenderPass> SingleTargetRenderInstance::createRenderPass (const vk::DeviceInterface& vki, 594 vk::VkDevice device, 595 const tcu::TextureFormat& format) 596 { 597 const vk::VkAttachmentDescription attachmentDescription = 598 { 599 (vk::VkAttachmentDescriptionFlags)0, 600 vk::mapTextureFormat(format), // format 601 vk::VK_SAMPLE_COUNT_1_BIT, // samples 602 vk::VK_ATTACHMENT_LOAD_OP_CLEAR, // loadOp 603 vk::VK_ATTACHMENT_STORE_OP_STORE, // storeOp 604 vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE, // stencilLoadOp 605 vk::VK_ATTACHMENT_STORE_OP_DONT_CARE, // stencilStoreOp 606 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // initialLayout 607 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // finalLayout 608 }; 609 const vk::VkAttachmentReference colorAttachment = 610 { 611 0u, // attachment 612 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // layout 613 }; 614 const vk::VkAttachmentReference depthStencilAttachment = 615 { 616 VK_ATTACHMENT_UNUSED, // attachment 617 vk::VK_IMAGE_LAYOUT_UNDEFINED // layout 618 }; 619 const vk::VkSubpassDescription subpass = 620 { 621 (vk::VkSubpassDescriptionFlags)0, 622 vk::VK_PIPELINE_BIND_POINT_GRAPHICS, // pipelineBindPoint 623 0u, // inputAttachmentCount 624 DE_NULL, // pInputAttachments 625 1u, // colorAttachmentCount 626 &colorAttachment, // pColorAttachments 627 DE_NULL, // pResolveAttachments 628 &depthStencilAttachment, // pDepthStencilAttachment 629 0u, // preserveAttachmentCount 630 DE_NULL // pPreserveAttachments 631 }; 632 const vk::VkRenderPassCreateInfo renderPassCreateInfo = 633 { 634 vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, 635 DE_NULL, 636 (vk::VkRenderPassCreateFlags)0, 637 1u, // attachmentCount 638 &attachmentDescription, // pAttachments 639 1u, // subpassCount 640 &subpass, // pSubpasses 641 0u, // dependencyCount 642 DE_NULL, // pDependencies 643 }; 644 645 return vk::createRenderPass(vki, device, &renderPassCreateInfo); 646 } 647 648 vk::Move<vk::VkFramebuffer> SingleTargetRenderInstance::createFramebuffer (const vk::DeviceInterface& vki, 649 vk::VkDevice device, 650 vk::VkRenderPass renderpass, 651 vk::VkImageView colorAttachmentView, 652 const tcu::UVec2& size) 653 { 654 const vk::VkFramebufferCreateInfo framebufferCreateInfo = 655 { 656 vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, 657 DE_NULL, 658 (vk::VkFramebufferCreateFlags)0, 659 renderpass, // renderPass 660 1u, // attachmentCount 661 &colorAttachmentView, // pAttachments 662 size.x(), // width 663 size.y(), // height 664 1, // layers 665 }; 666 667 return vk::createFramebuffer(vki, device, &framebufferCreateInfo); 668 } 669 670 vk::Move<vk::VkCommandPool> SingleTargetRenderInstance::createCommandPool (const vk::DeviceInterface& vki, 671 vk::VkDevice device, 672 deUint32 queueFamilyIndex) 673 { 674 const vk::VkCommandPoolCreateInfo createInfo = 675 { 676 vk::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, 677 DE_NULL, 678 vk::VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, // flags 679 queueFamilyIndex, // queueFamilyIndex 680 }; 681 return vk::createCommandPool(vki, device, &createInfo); 682 } 683 684 void SingleTargetRenderInstance::readRenderTarget (tcu::TextureLevel& dst) 685 { 686 const deUint64 pixelDataSize = (deUint64)(m_targetSize.x() * m_targetSize.y() * m_targetFormat.getPixelSize()); 687 const vk::VkBufferCreateInfo bufferCreateInfo = 688 { 689 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, 690 DE_NULL, 691 0u, // flags 692 pixelDataSize, // size 693 vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT, // usage 694 vk::VK_SHARING_MODE_EXCLUSIVE, // sharingMode 695 0u, // queueFamilyCount 696 DE_NULL, // pQueueFamilyIndices 697 }; 698 const vk::Unique<vk::VkBuffer> buffer (vk::createBuffer(m_vki, m_device, &bufferCreateInfo)); 699 const vk::VkImageSubresourceRange fullSubrange = 700 { 701 vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask 702 0u, // baseMipLevel 703 1u, // mipLevels 704 0u, // baseArraySlice 705 1u, // arraySize 706 }; 707 const vk::VkImageMemoryBarrier imageBarrier = 708 { 709 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 710 DE_NULL, 711 vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // srcAccessMask 712 vk::VK_ACCESS_TRANSFER_READ_BIT, // dstAccessMask 713 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // oldLayout 714 vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // newLayout 715 VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex 716 VK_QUEUE_FAMILY_IGNORED, // destQueueFamilyIndex 717 *m_colorAttachmentImage, // image 718 fullSubrange, // subresourceRange 719 }; 720 const vk::VkBufferMemoryBarrier memoryBarrier = 721 { 722 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 723 DE_NULL, 724 vk::VK_ACCESS_TRANSFER_WRITE_BIT, // srcAccessMask 725 vk::VK_ACCESS_HOST_READ_BIT, // dstAccessMask 726 VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex 727 VK_QUEUE_FAMILY_IGNORED, // destQueueFamilyIndex 728 *buffer, // buffer 729 0u, // offset 730 (vk::VkDeviceSize)pixelDataSize // size 731 }; 732 const vk::VkCommandBufferAllocateInfo cmdBufAllocInfo = 733 { 734 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, 735 DE_NULL, 736 *m_cmdPool, // cmdPool 737 vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY, // level 738 1u, // bufferCount 739 }; 740 const vk::VkFenceCreateInfo fenceCreateInfo = 741 { 742 vk::VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, 743 DE_NULL, 744 0u, // flags 745 }; 746 const vk::VkCommandBufferBeginInfo cmdBufBeginInfo = 747 { 748 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 749 DE_NULL, 750 vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, // flags 751 (const vk::VkCommandBufferInheritanceInfo*)DE_NULL, 752 }; 753 const vk::VkImageSubresourceLayers firstSlice = 754 { 755 vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspect 756 0, // mipLevel 757 0, // arrayLayer 758 1, // arraySize 759 }; 760 const vk::VkBufferImageCopy copyRegion = 761 { 762 0u, // bufferOffset 763 m_targetSize.x(), // bufferRowLength 764 m_targetSize.y(), // bufferImageHeight 765 firstSlice, // imageSubresource 766 { 0, 0, 0 }, // imageOffset 767 { m_targetSize.x(), m_targetSize.y(), 1u } // imageExtent 768 }; 769 770 const de::MovePtr<vk::Allocation> bufferMemory = allocateAndBindObjectMemory(m_vki, m_device, m_allocator, *buffer, vk::MemoryRequirement::HostVisible); 771 772 const vk::Unique<vk::VkCommandBuffer> cmd (vk::allocateCommandBuffer(m_vki, m_device, &cmdBufAllocInfo)); 773 const vk::Unique<vk::VkFence> cmdCompleteFence (vk::createFence(m_vki, m_device, &fenceCreateInfo)); 774 const deUint64 infiniteTimeout = ~(deUint64)0u; 775 776 // copy content to buffer 777 VK_CHECK(m_vki.beginCommandBuffer(*cmd, &cmdBufBeginInfo)); 778 m_vki.cmdPipelineBarrier(*cmd, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0, 779 0, (const vk::VkMemoryBarrier*)DE_NULL, 780 0, (const vk::VkBufferMemoryBarrier*)DE_NULL, 781 1, &imageBarrier); 782 m_vki.cmdCopyImageToBuffer(*cmd, *m_colorAttachmentImage, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *buffer, 1, ©Region); 783 m_vki.cmdPipelineBarrier(*cmd, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (vk::VkDependencyFlags)0, 784 0, (const vk::VkMemoryBarrier*)DE_NULL, 785 1, &memoryBarrier, 786 0, (const vk::VkImageMemoryBarrier*)DE_NULL); 787 VK_CHECK(m_vki.endCommandBuffer(*cmd)); 788 789 // wait for transfer to complete 790 { 791 const vk::VkSubmitInfo submitInfo = 792 { 793 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO, 794 DE_NULL, 795 0u, 796 (const vk::VkSemaphore*)0, 797 (const vk::VkPipelineStageFlags*)DE_NULL, 798 1u, 799 &cmd.get(), 800 0u, 801 (const vk::VkSemaphore*)0, 802 }; 803 804 VK_CHECK(m_vki.queueSubmit(m_queue, 1, &submitInfo, *cmdCompleteFence)); 805 } 806 VK_CHECK(m_vki.waitForFences(m_device, 1, &cmdCompleteFence.get(), 0u, infiniteTimeout)); // \note: timeout is failure 807 808 dst.setStorage(m_targetFormat, m_targetSize.x(), m_targetSize.y()); 809 810 // copy data 811 invalidateMappedMemoryRange(m_vki, m_device, bufferMemory->getMemory(), bufferMemory->getOffset(), pixelDataSize); 812 tcu::copy(dst, tcu::ConstPixelBufferAccess(dst.getFormat(), dst.getSize(), bufferMemory->getHostPtr())); 813 } 814 815 tcu::TestStatus SingleTargetRenderInstance::iterate (void) 816 { 817 tcu::TextureLevel resultImage; 818 819 // log 820 if (m_firstIteration) 821 { 822 logTestPlan(); 823 m_firstIteration = false; 824 } 825 826 // render 827 { 828 // transition to VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL 829 const vk::VkImageSubresourceRange fullSubrange = 830 { 831 vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask 832 0u, // baseMipLevel 833 1u, // mipLevels 834 0u, // baseArraySlice 835 1u, // arraySize 836 }; 837 const vk::VkImageMemoryBarrier imageBarrier = 838 { 839 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 840 DE_NULL, 841 0u, // srcAccessMask 842 vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // dstAccessMask 843 vk::VK_IMAGE_LAYOUT_UNDEFINED, // oldLayout 844 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // newLayout 845 VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex 846 VK_QUEUE_FAMILY_IGNORED, // destQueueFamilyIndex 847 *m_colorAttachmentImage, // image 848 fullSubrange, // subresourceRange 849 }; 850 const vk::VkCommandBufferAllocateInfo cmdBufAllocInfo = 851 { 852 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, 853 DE_NULL, 854 *m_cmdPool, // cmdPool 855 vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY, // level 856 1u, // count 857 }; 858 const vk::VkCommandBufferBeginInfo cmdBufBeginInfo = 859 { 860 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 861 DE_NULL, 862 vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, // flags 863 (const vk::VkCommandBufferInheritanceInfo*)DE_NULL, 864 }; 865 const vk::VkFenceCreateInfo fenceCreateInfo = 866 { 867 vk::VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, 868 DE_NULL, 869 (vk::VkFenceCreateFlags)0, 870 }; 871 872 const vk::Unique<vk::VkCommandBuffer> cmd (vk::allocateCommandBuffer(m_vki, m_device, &cmdBufAllocInfo)); 873 const vk::Unique<vk::VkFence> fence (vk::createFence(m_vki, m_device, &fenceCreateInfo)); 874 const deUint64 infiniteTimeout = ~(deUint64)0u; 875 876 VK_CHECK(m_vki.beginCommandBuffer(*cmd, &cmdBufBeginInfo)); 877 m_vki.cmdPipelineBarrier(*cmd, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (vk::VkDependencyFlags)0, 878 0, (const vk::VkMemoryBarrier*)DE_NULL, 879 0, (const vk::VkBufferMemoryBarrier*)DE_NULL, 880 1, &imageBarrier); 881 VK_CHECK(m_vki.endCommandBuffer(*cmd)); 882 883 { 884 const vk::VkSubmitInfo submitInfo = 885 { 886 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO, 887 DE_NULL, 888 0u, 889 (const vk::VkSemaphore*)0, 890 (const vk::VkPipelineStageFlags*)DE_NULL, 891 1u, 892 &cmd.get(), 893 0u, 894 (const vk::VkSemaphore*)0, 895 }; 896 897 VK_CHECK(m_vki.queueSubmit(m_queue, 1u, &submitInfo, *fence)); 898 } 899 VK_CHECK(m_vki.waitForFences(m_device, 1u, &fence.get(), VK_TRUE, infiniteTimeout)); 900 901 // and then render to 902 renderToTarget(); 903 } 904 905 // read and verify 906 readRenderTarget(resultImage); 907 return verifyResultImage(resultImage.getAccess()); 908 } 909 910 class RenderInstanceShaders 911 { 912 public: 913 RenderInstanceShaders (const vk::DeviceInterface& vki, 914 vk::VkDevice device, 915 const vk::VkPhysicalDeviceFeatures& deviceFeatures, 916 const vk::BinaryCollection& programCollection); 917 918 inline bool hasTessellationStage (void) const { return *m_tessCtrlShaderModule != 0 || *m_tessEvalShaderModule != 0; } 919 inline deUint32 getNumStages (void) const { return (deUint32)m_stageInfos.size(); } 920 inline const vk::VkPipelineShaderStageCreateInfo* getStages (void) const { return &m_stageInfos[0]; } 921 922 private: 923 void addStage (const vk::DeviceInterface& vki, 924 vk::VkDevice device, 925 const vk::VkPhysicalDeviceFeatures& deviceFeatures, 926 const vk::BinaryCollection& programCollection, 927 const char* name, 928 vk::VkShaderStageFlagBits stage, 929 vk::Move<vk::VkShaderModule>* outModule); 930 931 vk::VkPipelineShaderStageCreateInfo getShaderStageCreateInfo (vk::VkShaderStageFlagBits stage, vk::VkShaderModule shader) const; 932 933 vk::Move<vk::VkShaderModule> m_vertexShaderModule; 934 vk::Move<vk::VkShaderModule> m_tessCtrlShaderModule; 935 vk::Move<vk::VkShaderModule> m_tessEvalShaderModule; 936 vk::Move<vk::VkShaderModule> m_geometryShaderModule; 937 vk::Move<vk::VkShaderModule> m_fragmentShaderModule; 938 std::vector<vk::VkPipelineShaderStageCreateInfo> m_stageInfos; 939 }; 940 941 RenderInstanceShaders::RenderInstanceShaders (const vk::DeviceInterface& vki, 942 vk::VkDevice device, 943 const vk::VkPhysicalDeviceFeatures& deviceFeatures, 944 const vk::BinaryCollection& programCollection) 945 { 946 addStage(vki, device, deviceFeatures, programCollection, "vertex", vk::VK_SHADER_STAGE_VERTEX_BIT, &m_vertexShaderModule); 947 addStage(vki, device, deviceFeatures, programCollection, "tess_ctrl", vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, &m_tessCtrlShaderModule); 948 addStage(vki, device, deviceFeatures, programCollection, "tess_eval", vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, &m_tessEvalShaderModule); 949 addStage(vki, device, deviceFeatures, programCollection, "geometry", vk::VK_SHADER_STAGE_GEOMETRY_BIT, &m_geometryShaderModule); 950 addStage(vki, device, deviceFeatures, programCollection, "fragment", vk::VK_SHADER_STAGE_FRAGMENT_BIT, &m_fragmentShaderModule); 951 952 DE_ASSERT(!m_stageInfos.empty()); 953 } 954 955 void RenderInstanceShaders::addStage (const vk::DeviceInterface& vki, 956 vk::VkDevice device, 957 const vk::VkPhysicalDeviceFeatures& deviceFeatures, 958 const vk::BinaryCollection& programCollection, 959 const char* name, 960 vk::VkShaderStageFlagBits stage, 961 vk::Move<vk::VkShaderModule>* outModule) 962 { 963 if (programCollection.contains(name)) 964 { 965 if (vk::isShaderStageSupported(deviceFeatures, stage)) 966 { 967 vk::Move<vk::VkShaderModule> module = createShaderModule(vki, device, programCollection.get(name), (vk::VkShaderModuleCreateFlags)0); 968 969 m_stageInfos.push_back(getShaderStageCreateInfo(stage, *module)); 970 *outModule = module; 971 } 972 else 973 { 974 // Wait for the GPU to idle so that throwing the exception 975 // below doesn't free in-use GPU resource. 976 vki.deviceWaitIdle(device); 977 TCU_THROW(NotSupportedError, (de::toString(stage) + " is not supported").c_str()); 978 } 979 } 980 } 981 982 vk::VkPipelineShaderStageCreateInfo RenderInstanceShaders::getShaderStageCreateInfo (vk::VkShaderStageFlagBits stage, vk::VkShaderModule shader) const 983 { 984 const vk::VkPipelineShaderStageCreateInfo stageCreateInfo = 985 { 986 vk::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, 987 DE_NULL, 988 (vk::VkPipelineShaderStageCreateFlags)0, 989 stage, // stage 990 shader, // shader 991 "main", 992 DE_NULL, // pSpecializationInfo 993 }; 994 return stageCreateInfo; 995 } 996 997 class SingleCmdRenderInstance : public SingleTargetRenderInstance 998 { 999 public: 1000 SingleCmdRenderInstance (Context& context, 1001 bool isPrimaryCmdBuf, 1002 const tcu::UVec2& renderSize); 1003 1004 private: 1005 vk::Move<vk::VkPipeline> createPipeline (vk::VkPipelineLayout pipelineLayout); 1006 1007 virtual vk::VkPipelineLayout getPipelineLayout (void) const = 0; 1008 virtual void writeDrawCmdBuffer (vk::VkCommandBuffer cmd) const = 0; 1009 1010 void renderToTarget (void); 1011 1012 const bool m_isPrimaryCmdBuf; 1013 }; 1014 1015 SingleCmdRenderInstance::SingleCmdRenderInstance (Context& context, 1016 bool isPrimaryCmdBuf, 1017 const tcu::UVec2& renderSize) 1018 : SingleTargetRenderInstance (context, renderSize) 1019 , m_isPrimaryCmdBuf (isPrimaryCmdBuf) 1020 { 1021 } 1022 1023 vk::Move<vk::VkPipeline> SingleCmdRenderInstance::createPipeline (vk::VkPipelineLayout pipelineLayout) 1024 { 1025 const RenderInstanceShaders shaderStages (m_vki, m_device, m_context.getDeviceFeatures(), m_context.getBinaryCollection()); 1026 const vk::VkPrimitiveTopology topology = shaderStages.hasTessellationStage() ? vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST : vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; 1027 const vk::VkPipelineVertexInputStateCreateInfo vertexInputState = 1028 { 1029 vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, 1030 DE_NULL, 1031 (vk::VkPipelineVertexInputStateCreateFlags)0, 1032 0u, // bindingCount 1033 DE_NULL, // pVertexBindingDescriptions 1034 0u, // attributeCount 1035 DE_NULL, // pVertexAttributeDescriptions 1036 }; 1037 const vk::VkPipelineInputAssemblyStateCreateInfo iaState = 1038 { 1039 vk::VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, 1040 DE_NULL, 1041 (vk::VkPipelineInputAssemblyStateCreateFlags)0, 1042 topology, // topology 1043 VK_FALSE, // primitiveRestartEnable 1044 }; 1045 const vk::VkPipelineTessellationStateCreateInfo tessState = 1046 { 1047 vk::VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, 1048 DE_NULL, 1049 (vk::VkPipelineTessellationStateCreateFlags)0, 1050 3u, // patchControlPoints 1051 }; 1052 const vk::VkViewport viewport = 1053 { 1054 0.0f, // originX 1055 0.0f, // originY 1056 float(m_targetSize.x()), // width 1057 float(m_targetSize.y()), // height 1058 0.0f, // minDepth 1059 1.0f, // maxDepth 1060 }; 1061 const vk::VkRect2D renderArea = 1062 { 1063 { 0, 0 }, // offset 1064 { m_targetSize.x(), m_targetSize.y() }, // extent 1065 }; 1066 const vk::VkPipelineViewportStateCreateInfo vpState = 1067 { 1068 vk::VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, 1069 DE_NULL, 1070 (vk::VkPipelineViewportStateCreateFlags)0, 1071 1u, // viewportCount 1072 &viewport, 1073 1u, 1074 &renderArea, 1075 }; 1076 const vk::VkPipelineRasterizationStateCreateInfo rsState = 1077 { 1078 vk::VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, 1079 DE_NULL, 1080 (vk::VkPipelineRasterizationStateCreateFlags)0, 1081 VK_TRUE, // depthClipEnable 1082 VK_FALSE, // rasterizerDiscardEnable 1083 vk::VK_POLYGON_MODE_FILL, // fillMode 1084 vk::VK_CULL_MODE_NONE, // cullMode 1085 vk::VK_FRONT_FACE_COUNTER_CLOCKWISE, // frontFace 1086 VK_FALSE, // depthBiasEnable 1087 0.0f, // depthBias 1088 0.0f, // depthBiasClamp 1089 0.0f, // slopeScaledDepthBias 1090 1.0f, // lineWidth 1091 }; 1092 const vk::VkSampleMask sampleMask = 0x01u; 1093 const vk::VkPipelineMultisampleStateCreateInfo msState = 1094 { 1095 vk::VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, 1096 DE_NULL, 1097 (vk::VkPipelineMultisampleStateCreateFlags)0, 1098 vk::VK_SAMPLE_COUNT_1_BIT, // rasterSamples 1099 VK_FALSE, // sampleShadingEnable 1100 0.0f, // minSampleShading 1101 &sampleMask, // sampleMask 1102 VK_FALSE, // alphaToCoverageEnable 1103 VK_FALSE, // alphaToOneEnable 1104 }; 1105 const vk::VkPipelineDepthStencilStateCreateInfo dsState = 1106 { 1107 vk::VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, 1108 DE_NULL, 1109 (vk::VkPipelineDepthStencilStateCreateFlags)0, 1110 VK_FALSE, // depthTestEnable 1111 VK_FALSE, // depthWriteEnable 1112 vk::VK_COMPARE_OP_ALWAYS, // depthCompareOp 1113 VK_FALSE, // depthBoundsTestEnable 1114 VK_FALSE, // stencilTestEnable 1115 { vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_KEEP, vk::VK_COMPARE_OP_ALWAYS, 0u, 0u, 0u }, // front 1116 { vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_KEEP, vk::VK_COMPARE_OP_ALWAYS, 0u, 0u, 0u }, // back 1117 -1.0f, // minDepthBounds 1118 +1.0f, // maxDepthBounds 1119 }; 1120 const vk::VkPipelineColorBlendAttachmentState cbAttachment = 1121 { 1122 VK_FALSE, // blendEnable 1123 vk::VK_BLEND_FACTOR_ZERO, // srcBlendColor 1124 vk::VK_BLEND_FACTOR_ZERO, // destBlendColor 1125 vk::VK_BLEND_OP_ADD, // blendOpColor 1126 vk::VK_BLEND_FACTOR_ZERO, // srcBlendAlpha 1127 vk::VK_BLEND_FACTOR_ZERO, // destBlendAlpha 1128 vk::VK_BLEND_OP_ADD, // blendOpAlpha 1129 (vk::VK_COLOR_COMPONENT_R_BIT | 1130 vk::VK_COLOR_COMPONENT_G_BIT | 1131 vk::VK_COLOR_COMPONENT_B_BIT | 1132 vk::VK_COLOR_COMPONENT_A_BIT), // channelWriteMask 1133 }; 1134 const vk::VkPipelineColorBlendStateCreateInfo cbState = 1135 { 1136 vk::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, 1137 DE_NULL, 1138 (vk::VkPipelineColorBlendStateCreateFlags)0, 1139 VK_FALSE, // logicOpEnable 1140 vk::VK_LOGIC_OP_CLEAR, // logicOp 1141 1u, // attachmentCount 1142 &cbAttachment, // pAttachments 1143 { 0.0f, 0.0f, 0.0f, 0.0f }, // blendConst 1144 }; 1145 const vk::VkGraphicsPipelineCreateInfo createInfo = 1146 { 1147 vk::VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, 1148 DE_NULL, 1149 (vk::VkPipelineCreateFlags)0, 1150 shaderStages.getNumStages(), // stageCount 1151 shaderStages.getStages(), // pStages 1152 &vertexInputState, // pVertexInputState 1153 &iaState, // pInputAssemblyState 1154 (shaderStages.hasTessellationStage() ? &tessState : DE_NULL), // pTessellationState 1155 &vpState, // pViewportState 1156 &rsState, // pRasterState 1157 &msState, // pMultisampleState 1158 &dsState, // pDepthStencilState 1159 &cbState, // pColorBlendState 1160 (const vk::VkPipelineDynamicStateCreateInfo*)DE_NULL, // pDynamicState 1161 pipelineLayout, // layout 1162 *m_renderPass, // renderPass 1163 0u, // subpass 1164 (vk::VkPipeline)0, // basePipelineHandle 1165 0u, // basePipelineIndex 1166 }; 1167 return createGraphicsPipeline(m_vki, m_device, (vk::VkPipelineCache)0u, &createInfo); 1168 } 1169 1170 void SingleCmdRenderInstance::renderToTarget (void) 1171 { 1172 const vk::VkRect2D renderArea = 1173 { 1174 { 0, 0 }, // offset 1175 { m_targetSize.x(), m_targetSize.y() }, // extent 1176 }; 1177 const vk::VkCommandBufferAllocateInfo mainCmdBufCreateInfo = 1178 { 1179 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, 1180 DE_NULL, 1181 *m_cmdPool, // cmdPool 1182 vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY, // level 1183 1u, // count 1184 }; 1185 const vk::VkCommandBufferBeginInfo mainCmdBufBeginInfo = 1186 { 1187 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 1188 DE_NULL, 1189 vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, // flags 1190 (const vk::VkCommandBufferInheritanceInfo*)DE_NULL, 1191 }; 1192 const vk::VkCommandBufferAllocateInfo passCmdBufCreateInfo = 1193 { 1194 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, 1195 DE_NULL, 1196 *m_cmdPool, // cmdPool 1197 vk::VK_COMMAND_BUFFER_LEVEL_SECONDARY, // level 1198 1u, // count 1199 }; 1200 const vk::VkCommandBufferInheritanceInfo passCmdBufInheritInfo = 1201 { 1202 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 1203 DE_NULL, 1204 (vk::VkRenderPass)*m_renderPass, // renderPass 1205 0u, // subpass 1206 (vk::VkFramebuffer)*m_framebuffer, // framebuffer 1207 VK_FALSE, // occlusionQueryEnable 1208 (vk::VkQueryControlFlags)0, 1209 (vk::VkQueryPipelineStatisticFlags)0, 1210 }; 1211 const vk::VkCommandBufferBeginInfo passCmdBufBeginInfo = 1212 { 1213 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 1214 DE_NULL, 1215 vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT | 1216 vk::VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, // flags 1217 &passCmdBufInheritInfo, 1218 }; 1219 const vk::VkFenceCreateInfo fenceCreateInfo = 1220 { 1221 vk::VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, 1222 DE_NULL, 1223 0u, // flags 1224 }; 1225 const vk::VkClearValue clearValue = vk::makeClearValueColorF32(0.0f, 0.0f, 0.0f, 0.0f); 1226 const vk::VkRenderPassBeginInfo renderPassBeginInfo = 1227 { 1228 vk::VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, 1229 DE_NULL, 1230 *m_renderPass, // renderPass 1231 *m_framebuffer, // framebuffer 1232 renderArea, // renderArea 1233 1u, // clearValueCount 1234 &clearValue, // pClearValues 1235 }; 1236 1237 const vk::VkPipelineLayout pipelineLayout (getPipelineLayout()); 1238 const vk::Unique<vk::VkPipeline> pipeline (createPipeline(pipelineLayout)); 1239 const vk::Unique<vk::VkCommandBuffer> mainCmd (vk::allocateCommandBuffer(m_vki, m_device, &mainCmdBufCreateInfo)); 1240 const vk::Unique<vk::VkCommandBuffer> passCmd ((m_isPrimaryCmdBuf) ? (vk::Move<vk::VkCommandBuffer>()) : (vk::allocateCommandBuffer(m_vki, m_device, &passCmdBufCreateInfo))); 1241 const vk::Unique<vk::VkFence> fence (vk::createFence(m_vki, m_device, &fenceCreateInfo)); 1242 const deUint64 infiniteTimeout = ~(deUint64)0u; 1243 const vk::VkSubpassContents passContents = (m_isPrimaryCmdBuf) ? (vk::VK_SUBPASS_CONTENTS_INLINE) : (vk::VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS); 1244 1245 VK_CHECK(m_vki.beginCommandBuffer(*mainCmd, &mainCmdBufBeginInfo)); 1246 m_vki.cmdBeginRenderPass(*mainCmd, &renderPassBeginInfo, passContents); 1247 1248 if (m_isPrimaryCmdBuf) 1249 { 1250 m_vki.cmdBindPipeline(*mainCmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline); 1251 writeDrawCmdBuffer(*mainCmd); 1252 } 1253 else 1254 { 1255 VK_CHECK(m_vki.beginCommandBuffer(*passCmd, &passCmdBufBeginInfo)); 1256 m_vki.cmdBindPipeline(*passCmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline); 1257 writeDrawCmdBuffer(*passCmd); 1258 VK_CHECK(m_vki.endCommandBuffer(*passCmd)); 1259 1260 m_vki.cmdExecuteCommands(*mainCmd, 1, &passCmd.get()); 1261 } 1262 1263 m_vki.cmdEndRenderPass(*mainCmd); 1264 VK_CHECK(m_vki.endCommandBuffer(*mainCmd)); 1265 1266 // submit and wait for them to finish before exiting scope. (Killing in-flight objects is a no-no). 1267 { 1268 const vk::VkSubmitInfo submitInfo = 1269 { 1270 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO, 1271 DE_NULL, 1272 0u, 1273 (const vk::VkSemaphore*)0, 1274 (const vk::VkPipelineStageFlags*)DE_NULL, 1275 1u, 1276 &mainCmd.get(), 1277 0u, 1278 (const vk::VkSemaphore*)0, 1279 }; 1280 VK_CHECK(m_vki.queueSubmit(m_queue, 1, &submitInfo, *fence)); 1281 } 1282 VK_CHECK(m_vki.waitForFences(m_device, 1, &fence.get(), 0u, infiniteTimeout)); // \note: timeout is failure 1283 } 1284 1285 enum ShaderInputInterface 1286 { 1287 SHADER_INPUT_SINGLE_DESCRIPTOR = 0, //!< one descriptor 1288 SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS, //!< multiple descriptors with contiguous binding id's 1289 SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS, //!< multiple descriptors with discontiguous binding id's 1290 SHADER_INPUT_DESCRIPTOR_ARRAY, //!< descriptor array 1291 1292 SHADER_INPUT_LAST 1293 }; 1294 1295 deUint32 getInterfaceNumResources (ShaderInputInterface shaderInterface) 1296 { 1297 switch (shaderInterface) 1298 { 1299 case SHADER_INPUT_SINGLE_DESCRIPTOR: return 1u; 1300 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS: return 2u; 1301 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS: return 2u; 1302 case SHADER_INPUT_DESCRIPTOR_ARRAY: return 2u; 1303 1304 default: 1305 DE_FATAL("Impossible"); 1306 return 0u; 1307 } 1308 } 1309 1310 class BufferRenderInstance : public SingleCmdRenderInstance 1311 { 1312 public: 1313 BufferRenderInstance (Context& context, 1314 DescriptorUpdateMethod updateMethod, 1315 bool isPrimaryCmdBuf, 1316 vk::VkDescriptorType descriptorType, 1317 vk::VkShaderStageFlags stageFlags, 1318 ShaderInputInterface shaderInterface, 1319 bool viewOffset, 1320 bool dynamicOffset, 1321 bool dynamicOffsetNonZero); 1322 1323 static vk::Move<vk::VkBuffer> createSourceBuffer (const vk::DeviceInterface& vki, 1324 vk::VkDevice device, 1325 vk::Allocator& allocator, 1326 vk::VkDescriptorType descriptorType, 1327 deUint32 offset, 1328 deUint32 bufferSize, 1329 de::MovePtr<vk::Allocation>* outMemory); 1330 1331 static vk::Move<vk::VkDescriptorPool> createDescriptorPool (const vk::DeviceInterface& vki, 1332 vk::VkDevice device, 1333 vk::VkDescriptorType descriptorType, 1334 ShaderInputInterface shaderInterface); 1335 1336 static vk::Move<vk::VkDescriptorSetLayout> createDescriptorSetLayout (const vk::DeviceInterface& vki, 1337 vk::VkDevice device, 1338 vk::VkDescriptorType descriptorType, 1339 ShaderInputInterface shaderInterface, 1340 vk::VkShaderStageFlags stageFlags, 1341 DescriptorUpdateMethod updateMethod); 1342 1343 static vk::Move<vk::VkDescriptorSet> createDescriptorSet (const vk::DeviceInterface& vki, 1344 DescriptorUpdateMethod updateMethod, 1345 vk::VkDevice device, 1346 vk::VkDescriptorSetLayout descriptorSetLayout, 1347 vk::VkDescriptorPool descriptorPool, 1348 vk::VkDescriptorType descriptorType, 1349 ShaderInputInterface shaderInterface, 1350 vk::VkBuffer sourceBufferA, 1351 const deUint32 viewOffsetA, 1352 vk::VkBuffer sourceBufferB, 1353 const deUint32 viewOffsetB, 1354 vk::DescriptorSetUpdateBuilder& updateBuilder, 1355 vk::Move<vk::VkDescriptorUpdateTemplateKHR>& updateTemplate, 1356 RawUpdateRegistry& updateRegistry, 1357 vk::VkPipelineLayout pipelineLayout = DE_NULL); 1358 1359 static vk::Move<vk::VkPipelineLayout> createPipelineLayout (const vk::DeviceInterface& vki, 1360 vk::VkDevice device, 1361 vk::VkDescriptorSetLayout descriptorSetLayout); 1362 1363 static void writeDescriptorSet (const vk::DeviceInterface& vki, 1364 vk::VkDevice device, 1365 vk::VkDescriptorSetLayout descriptorSetLayout, 1366 vk::VkDescriptorPool descriptorPool, 1367 vk::VkDescriptorType descriptorType, 1368 ShaderInputInterface shaderInterface, 1369 vk::VkBuffer sourceBufferA, 1370 const deUint32 viewOffsetA, 1371 vk::VkBuffer sourceBufferB, 1372 const deUint32 viewOffsetB, 1373 vk::VkDescriptorSet descriptorSet, 1374 vk::DescriptorSetUpdateBuilder& updateBuilder, 1375 DescriptorUpdateMethod updateMethod = DESCRIPTOR_UPDATE_METHOD_NORMAL); 1376 1377 static void writeDescriptorSetWithTemplate (const vk::DeviceInterface& vki, 1378 vk::VkDevice device, 1379 vk::VkDescriptorSetLayout descriptorSetLayout, 1380 vk::VkDescriptorPool descriptorPool, 1381 vk::VkDescriptorType descriptorType, 1382 ShaderInputInterface shaderInterface, 1383 vk::VkBuffer sourceBufferA, 1384 const deUint32 viewOffsetA, 1385 vk::VkBuffer sourceBufferB, 1386 const deUint32 viewOffsetB, 1387 vk::VkDescriptorSet descriptorSet, 1388 vk::Move<vk::VkDescriptorUpdateTemplateKHR>& updateTemplate, 1389 RawUpdateRegistry& updateRegistry, 1390 bool withPush = false, 1391 vk::VkPipelineLayout pipelineLayout = 0); 1392 1393 void logTestPlan (void) const; 1394 vk::VkPipelineLayout getPipelineLayout (void) const; 1395 void writeDrawCmdBuffer (vk::VkCommandBuffer cmd) const; 1396 tcu::TestStatus verifyResultImage (const tcu::ConstPixelBufferAccess& result) const; 1397 1398 enum 1399 { 1400 RENDER_SIZE = 128, 1401 BUFFER_DATA_SIZE = 8 * sizeof(float), 1402 BUFFER_SIZE_A = 2048, //!< a lot more than required 1403 BUFFER_SIZE_B = 2560, //!< a lot more than required 1404 1405 STATIC_OFFSET_VALUE_A = 256, 1406 DYNAMIC_OFFSET_VALUE_A = 512, 1407 STATIC_OFFSET_VALUE_B = 1024, 1408 DYNAMIC_OFFSET_VALUE_B = 768, 1409 }; 1410 1411 const DescriptorUpdateMethod m_updateMethod; 1412 const vk::VkDescriptorType m_descriptorType; 1413 const ShaderInputInterface m_shaderInterface; 1414 const bool m_setViewOffset; 1415 const bool m_setDynamicOffset; 1416 const bool m_dynamicOffsetNonZero; 1417 const vk::VkShaderStageFlags m_stageFlags; 1418 1419 const deUint32 m_viewOffsetA; 1420 const deUint32 m_viewOffsetB; 1421 const deUint32 m_dynamicOffsetA; 1422 const deUint32 m_dynamicOffsetB; 1423 const deUint32 m_effectiveOffsetA; 1424 const deUint32 m_effectiveOffsetB; 1425 const deUint32 m_bufferSizeA; 1426 const deUint32 m_bufferSizeB; 1427 1428 de::MovePtr<vk::Allocation> m_bufferMemoryA; 1429 de::MovePtr<vk::Allocation> m_bufferMemoryB; 1430 const vk::Unique<vk::VkBuffer> m_sourceBufferA; 1431 const vk::Unique<vk::VkBuffer> m_sourceBufferB; 1432 const vk::Unique<vk::VkDescriptorPool> m_descriptorPool; 1433 vk::Move<vk::VkDescriptorUpdateTemplateKHR> m_updateTemplate; 1434 RawUpdateRegistry m_updateRegistry; 1435 vk::DescriptorSetUpdateBuilder m_updateBuilder; 1436 const vk::Unique<vk::VkDescriptorSetLayout> m_descriptorSetLayout; 1437 const vk::Unique<vk::VkPipelineLayout> m_pipelineLayout; 1438 const vk::Unique<vk::VkDescriptorSet> m_descriptorSet; 1439 }; 1440 1441 BufferRenderInstance::BufferRenderInstance (Context& context, 1442 DescriptorUpdateMethod updateMethod, 1443 bool isPrimaryCmdBuf, 1444 vk::VkDescriptorType descriptorType, 1445 vk::VkShaderStageFlags stageFlags, 1446 ShaderInputInterface shaderInterface, 1447 bool viewOffset, 1448 bool dynamicOffset, 1449 bool dynamicOffsetNonZero) 1450 : SingleCmdRenderInstance (context, isPrimaryCmdBuf, tcu::UVec2(RENDER_SIZE, RENDER_SIZE)) 1451 , m_updateMethod (updateMethod) 1452 , m_descriptorType (descriptorType) 1453 , m_shaderInterface (shaderInterface) 1454 , m_setViewOffset (viewOffset) 1455 , m_setDynamicOffset (dynamicOffset) 1456 , m_dynamicOffsetNonZero (dynamicOffsetNonZero) 1457 , m_stageFlags (stageFlags) 1458 , m_viewOffsetA ((m_setViewOffset) ? ((deUint32)STATIC_OFFSET_VALUE_A) : (0u)) 1459 , m_viewOffsetB ((m_setViewOffset) ? ((deUint32)STATIC_OFFSET_VALUE_B) : (0u)) 1460 , m_dynamicOffsetA ((dynamicOffsetNonZero) ? ((deUint32)DYNAMIC_OFFSET_VALUE_A) : (0u)) 1461 , m_dynamicOffsetB ((dynamicOffsetNonZero) ? ((deUint32)DYNAMIC_OFFSET_VALUE_B) : (0u)) 1462 , m_effectiveOffsetA ((isDynamicDescriptorType(m_descriptorType)) ? (m_viewOffsetA + m_dynamicOffsetA) : (m_viewOffsetA)) 1463 , m_effectiveOffsetB ((isDynamicDescriptorType(m_descriptorType)) ? (m_viewOffsetB + m_dynamicOffsetB) : (m_viewOffsetB)) 1464 , m_bufferSizeA (BUFFER_SIZE_A) 1465 , m_bufferSizeB (BUFFER_SIZE_B) 1466 , m_bufferMemoryA (DE_NULL) 1467 , m_bufferMemoryB (DE_NULL) 1468 , m_sourceBufferA (createSourceBuffer(m_vki, m_device, m_allocator, m_descriptorType, m_effectiveOffsetA, m_bufferSizeA, &m_bufferMemoryA)) 1469 , m_sourceBufferB ((getInterfaceNumResources(m_shaderInterface) == 1u) 1470 ? vk::Move<vk::VkBuffer>() 1471 : createSourceBuffer(m_vki, m_device, m_allocator, m_descriptorType, m_effectiveOffsetB, m_bufferSizeB, &m_bufferMemoryB)) 1472 , m_descriptorPool (createDescriptorPool(m_vki, m_device, m_descriptorType, m_shaderInterface)) 1473 , m_updateTemplate () 1474 , m_updateRegistry () 1475 , m_updateBuilder () 1476 , m_descriptorSetLayout (createDescriptorSetLayout(m_vki, m_device, m_descriptorType, m_shaderInterface, m_stageFlags, m_updateMethod)) 1477 , m_pipelineLayout (createPipelineLayout(m_vki, m_device, *m_descriptorSetLayout)) 1478 , m_descriptorSet (createDescriptorSet(m_vki, m_updateMethod, m_device, *m_descriptorSetLayout, *m_descriptorPool, m_descriptorType, m_shaderInterface, *m_sourceBufferA, m_viewOffsetA, *m_sourceBufferB, m_viewOffsetB, m_updateBuilder, m_updateTemplate, m_updateRegistry, *m_pipelineLayout)) 1479 { 1480 if (m_setDynamicOffset) 1481 DE_ASSERT(isDynamicDescriptorType(m_descriptorType)); 1482 if (m_dynamicOffsetNonZero) 1483 DE_ASSERT(m_setDynamicOffset); 1484 } 1485 1486 vk::Move<vk::VkBuffer> BufferRenderInstance::createSourceBuffer (const vk::DeviceInterface& vki, 1487 vk::VkDevice device, 1488 vk::Allocator& allocator, 1489 vk::VkDescriptorType descriptorType, 1490 deUint32 offset, 1491 deUint32 bufferSize, 1492 de::MovePtr<vk::Allocation>* outMemory) 1493 { 1494 static const float s_colors[] = 1495 { 1496 0.0f, 1.0f, 0.0f, 1.0f, // green 1497 1.0f, 1.0f, 0.0f, 1.0f, // yellow 1498 }; 1499 DE_STATIC_ASSERT(sizeof(s_colors) == BUFFER_DATA_SIZE); 1500 DE_ASSERT(offset + BUFFER_DATA_SIZE <= bufferSize); 1501 DE_ASSERT(offset % sizeof(float) == 0); 1502 DE_ASSERT(bufferSize % sizeof(float) == 0); 1503 1504 const bool isUniformBuffer = isUniformDescriptorType(descriptorType); 1505 const vk::VkBufferUsageFlags usageFlags = (isUniformBuffer) ? (vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) : (vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT); 1506 const float preGuardValue = 0.5f; 1507 const float postGuardValue = 0.75f; 1508 const vk::VkBufferCreateInfo bufferCreateInfo = 1509 { 1510 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, 1511 DE_NULL, 1512 0u, // flags 1513 bufferSize, // size 1514 usageFlags, // usage 1515 vk::VK_SHARING_MODE_EXCLUSIVE, // sharingMode 1516 0u, // queueFamilyCount 1517 DE_NULL, // pQueueFamilyIndices 1518 }; 1519 vk::Move<vk::VkBuffer> buffer (vk::createBuffer(vki, device, &bufferCreateInfo)); 1520 de::MovePtr<vk::Allocation> bufferMemory = allocateAndBindObjectMemory(vki, device, allocator, *buffer, vk::MemoryRequirement::HostVisible); 1521 void* const mapPtr = bufferMemory->getHostPtr(); 1522 1523 // guard with interesting values 1524 for (size_t preGuardOffset = 0; preGuardOffset + sizeof(float) <= (size_t)offset; preGuardOffset += sizeof(float)) 1525 deMemcpy((deUint8*)mapPtr + preGuardOffset, &preGuardValue, sizeof(float)); 1526 1527 deMemcpy((deUint8*)mapPtr + offset, s_colors, sizeof(s_colors)); 1528 for (size_t postGuardOffset = (size_t)offset + sizeof(s_colors); postGuardOffset + sizeof(float) <= (size_t)bufferSize; postGuardOffset += sizeof(float)) 1529 deMemcpy((deUint8*)mapPtr + postGuardOffset, &postGuardValue, sizeof(float)); 1530 deMemset((deUint8*)mapPtr + offset + sizeof(s_colors), 0x5A, (size_t)bufferSize - (size_t)offset - sizeof(s_colors)); // fill with interesting pattern that produces valid floats 1531 1532 flushMappedMemoryRange(vki, device, bufferMemory->getMemory(), bufferMemory->getOffset(), bufferSize); 1533 1534 // Flushed host-visible memory is automatically made available to the GPU, no barrier is needed. 1535 1536 *outMemory = bufferMemory; 1537 return buffer; 1538 } 1539 1540 vk::Move<vk::VkDescriptorPool> BufferRenderInstance::createDescriptorPool (const vk::DeviceInterface& vki, 1541 vk::VkDevice device, 1542 vk::VkDescriptorType descriptorType, 1543 ShaderInputInterface shaderInterface) 1544 { 1545 return vk::DescriptorPoolBuilder() 1546 .addType(descriptorType, getInterfaceNumResources(shaderInterface)) 1547 .build(vki, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1); 1548 } 1549 1550 vk::Move<vk::VkDescriptorSetLayout> BufferRenderInstance::createDescriptorSetLayout (const vk::DeviceInterface& vki, 1551 vk::VkDevice device, 1552 vk::VkDescriptorType descriptorType, 1553 ShaderInputInterface shaderInterface, 1554 vk::VkShaderStageFlags stageFlags, 1555 DescriptorUpdateMethod updateMethod) 1556 { 1557 vk::DescriptorSetLayoutBuilder builder; 1558 vk::VkDescriptorSetLayoutCreateFlags extraFlags = 0; 1559 1560 if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE || 1561 updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH) 1562 { 1563 extraFlags |= vk::VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR; 1564 } 1565 1566 switch (shaderInterface) 1567 { 1568 case SHADER_INPUT_SINGLE_DESCRIPTOR: 1569 builder.addSingleBinding(descriptorType, stageFlags); 1570 break; 1571 1572 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS: 1573 builder.addSingleBinding(descriptorType, stageFlags); 1574 builder.addSingleBinding(descriptorType, stageFlags); 1575 break; 1576 1577 case SHADER_INPUT_DESCRIPTOR_ARRAY: 1578 builder.addArrayBinding(descriptorType, 2u, stageFlags); 1579 break; 1580 1581 default: 1582 DE_FATAL("Impossible"); 1583 } 1584 1585 return builder.build(vki, device, extraFlags); 1586 } 1587 1588 vk::Move<vk::VkDescriptorSet> BufferRenderInstance::createDescriptorSet (const vk::DeviceInterface& vki, 1589 DescriptorUpdateMethod updateMethod, 1590 vk::VkDevice device, 1591 vk::VkDescriptorSetLayout descriptorSetLayout, 1592 vk::VkDescriptorPool descriptorPool, 1593 vk::VkDescriptorType descriptorType, 1594 ShaderInputInterface shaderInterface, 1595 vk::VkBuffer bufferA, 1596 deUint32 offsetA, 1597 vk::VkBuffer bufferB, 1598 deUint32 offsetB, 1599 vk::DescriptorSetUpdateBuilder& updateBuilder, 1600 vk::Move<vk::VkDescriptorUpdateTemplateKHR>& updateTemplate, 1601 RawUpdateRegistry& updateRegistry, 1602 vk::VkPipelineLayout pipelineLayout) 1603 { 1604 const vk::VkDescriptorSetAllocateInfo allocInfo = 1605 { 1606 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, 1607 DE_NULL, 1608 descriptorPool, 1609 1u, 1610 &descriptorSetLayout 1611 }; 1612 1613 vk::Move<vk::VkDescriptorSet> descriptorSet; 1614 if (updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH && updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE) 1615 { 1616 descriptorSet = allocateDescriptorSet(vki, device, &allocInfo); 1617 } 1618 else 1619 { 1620 descriptorSet = vk::Move<vk::VkDescriptorSet>(); 1621 } 1622 1623 if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_TEMPLATE) 1624 { 1625 writeDescriptorSetWithTemplate(vki, device, descriptorSetLayout, descriptorPool, descriptorType, shaderInterface, bufferA, offsetA, bufferB, offsetB, *descriptorSet, updateTemplate, updateRegistry); 1626 } 1627 else if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE) 1628 { 1629 writeDescriptorSetWithTemplate(vki, device, descriptorSetLayout, descriptorPool, descriptorType, shaderInterface, bufferA, offsetA, bufferB, offsetB, *descriptorSet, updateTemplate, updateRegistry, true, pipelineLayout); 1630 } 1631 else if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH) 1632 { 1633 writeDescriptorSet(vki, device, descriptorSetLayout, descriptorPool, descriptorType, shaderInterface, bufferA, offsetA, bufferB, offsetB, *descriptorSet, updateBuilder, updateMethod); 1634 } 1635 else if (updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL) 1636 { 1637 writeDescriptorSet(vki, device, descriptorSetLayout, descriptorPool, descriptorType, shaderInterface, bufferA, offsetA, bufferB, offsetB, *descriptorSet, updateBuilder); 1638 } 1639 1640 return descriptorSet; 1641 } 1642 1643 void BufferRenderInstance::writeDescriptorSet (const vk::DeviceInterface& vki, 1644 vk::VkDevice device, 1645 vk::VkDescriptorSetLayout descriptorSetLayout, 1646 vk::VkDescriptorPool descriptorPool, 1647 vk::VkDescriptorType descriptorType, 1648 ShaderInputInterface shaderInterface, 1649 vk::VkBuffer bufferA, 1650 const deUint32 offsetA, 1651 vk::VkBuffer bufferB, 1652 const deUint32 offsetB, 1653 vk::VkDescriptorSet descriptorSet, 1654 vk::DescriptorSetUpdateBuilder& updateBuilder, 1655 DescriptorUpdateMethod updateMethod) 1656 { 1657 DE_UNREF(descriptorSetLayout); 1658 DE_UNREF(descriptorPool); 1659 const vk::VkDescriptorBufferInfo bufferInfos[2] = 1660 { 1661 vk::makeDescriptorBufferInfo(bufferA, (vk::VkDeviceSize)offsetA, (vk::VkDeviceSize)BUFFER_DATA_SIZE), 1662 vk::makeDescriptorBufferInfo(bufferB, (vk::VkDeviceSize)offsetB, (vk::VkDeviceSize)BUFFER_DATA_SIZE), 1663 }; 1664 1665 switch (shaderInterface) 1666 { 1667 case SHADER_INPUT_SINGLE_DESCRIPTOR: 1668 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType, &bufferInfos[0]); 1669 break; 1670 1671 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS: 1672 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType, &bufferInfos[0]); 1673 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), descriptorType, &bufferInfos[1]); 1674 break; 1675 1676 case SHADER_INPUT_DESCRIPTOR_ARRAY: 1677 updateBuilder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType, 2u, bufferInfos); 1678 break; 1679 1680 default: 1681 DE_FATAL("Impossible"); 1682 } 1683 1684 if (updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL) 1685 { 1686 updateBuilder.update(vki, device); 1687 } 1688 } 1689 1690 void BufferRenderInstance::writeDescriptorSetWithTemplate (const vk::DeviceInterface& vki, 1691 vk::VkDevice device, 1692 vk::VkDescriptorSetLayout layout, 1693 vk::VkDescriptorPool descriptorPool, 1694 vk::VkDescriptorType descriptorType, 1695 ShaderInputInterface shaderInterface, 1696 vk::VkBuffer bufferA, 1697 const deUint32 offsetA, 1698 vk::VkBuffer bufferB, 1699 const deUint32 offsetB, 1700 vk::VkDescriptorSet descriptorSet, 1701 vk::Move<vk::VkDescriptorUpdateTemplateKHR>& updateTemplate, 1702 RawUpdateRegistry& updateRegistry, 1703 bool withPush, 1704 vk::VkPipelineLayout pipelineLayout) 1705 { 1706 DE_UNREF(descriptorPool); 1707 const vk::VkDescriptorBufferInfo bufferInfos[2] = 1708 { 1709 vk::makeDescriptorBufferInfo(bufferA, (vk::VkDeviceSize)offsetA, (vk::VkDeviceSize)BUFFER_DATA_SIZE), 1710 vk::makeDescriptorBufferInfo(bufferB, (vk::VkDeviceSize)offsetB, (vk::VkDeviceSize)BUFFER_DATA_SIZE), 1711 }; 1712 std::vector<vk::VkDescriptorUpdateTemplateEntryKHR> updateEntries; 1713 vk::VkDescriptorUpdateTemplateCreateInfoKHR templateCreateInfo = 1714 { 1715 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR, 1716 DE_NULL, 1717 0, 1718 0, // descriptorUpdateEntryCount 1719 DE_NULL, // pDescriptorUpdateEntries 1720 withPush ? vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR : vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR, 1721 layout, 1722 vk::VK_PIPELINE_BIND_POINT_GRAPHICS, 1723 pipelineLayout, 1724 0 1725 }; 1726 updateRegistry.addWriteObject(bufferInfos[0]); 1727 updateRegistry.addWriteObject(bufferInfos[1]); 1728 1729 switch (shaderInterface) 1730 { 1731 case SHADER_INPUT_SINGLE_DESCRIPTOR: 1732 updateEntries.push_back(createTemplateBinding(0u, 0, 1, descriptorType, updateRegistry.getWriteObjectOffset(0), 0)); 1733 break; 1734 1735 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS: 1736 updateEntries.push_back(createTemplateBinding(0u, 0, 1, descriptorType, updateRegistry.getWriteObjectOffset(0), 0)); 1737 updateEntries.push_back(createTemplateBinding(1u, 0, 1, descriptorType, updateRegistry.getWriteObjectOffset(1), 0)); 1738 break; 1739 1740 case SHADER_INPUT_DESCRIPTOR_ARRAY: 1741 updateEntries.push_back(createTemplateBinding(0u, 0, 2, descriptorType, updateRegistry.getWriteObjectOffset(0), sizeof(bufferInfos[0]))); 1742 break; 1743 1744 default: 1745 DE_FATAL("Impossible"); 1746 } 1747 1748 templateCreateInfo.pDescriptorUpdateEntries = &updateEntries[0]; 1749 templateCreateInfo.descriptorUpdateEntryCount = (deUint32)updateEntries.size(); 1750 1751 updateTemplate = vk::createDescriptorUpdateTemplateKHR(vki, device, &templateCreateInfo); 1752 1753 if (!withPush) 1754 { 1755 vki.updateDescriptorSetWithTemplateKHR(device, descriptorSet, *updateTemplate, updateRegistry.getRawPointer()); 1756 } 1757 } 1758 1759 vk::Move<vk::VkPipelineLayout> BufferRenderInstance::createPipelineLayout (const vk::DeviceInterface& vki, 1760 vk::VkDevice device, 1761 vk::VkDescriptorSetLayout descriptorSetLayout) 1762 { 1763 const vk::VkPipelineLayoutCreateInfo createInfo = 1764 { 1765 vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, 1766 DE_NULL, 1767 (vk::VkPipelineLayoutCreateFlags)0, 1768 1, // descriptorSetCount 1769 &descriptorSetLayout, // pSetLayouts 1770 0u, // pushConstantRangeCount 1771 DE_NULL, // pPushConstantRanges 1772 }; 1773 1774 return vk::createPipelineLayout(vki, device, &createInfo); 1775 } 1776 1777 void BufferRenderInstance::logTestPlan (void) const 1778 { 1779 std::ostringstream msg; 1780 1781 msg << "Rendering 2x2 yellow-green grid.\n" 1782 << "Single descriptor set. Descriptor set contains " 1783 << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" : 1784 (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? "two" : 1785 (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" : 1786 (const char*)DE_NULL) 1787 << " descriptor(s) of type " << vk::getDescriptorTypeName(m_descriptorType) << "\n" 1788 << "Buffer view(s) have " << ((m_setViewOffset) ? ("non-") : ("")) << "zero offset.\n"; 1789 1790 if (isDynamicDescriptorType(m_descriptorType)) 1791 { 1792 if (m_setDynamicOffset) 1793 { 1794 msg << "Source buffer(s) are given a dynamic offset at bind time.\n" 1795 << "The supplied dynamic offset is " << ((m_dynamicOffsetNonZero) ? ("non-") : ("")) << "zero.\n"; 1796 } 1797 else 1798 { 1799 msg << "Dynamic offset is not supplied at bind time. Expecting bind to offset 0.\n"; 1800 } 1801 } 1802 1803 if (m_stageFlags == 0u) 1804 { 1805 msg << "Descriptors are not accessed in any shader stage.\n"; 1806 } 1807 else 1808 { 1809 msg << "Descriptors are accessed in {" 1810 << (((m_stageFlags & vk::VK_SHADER_STAGE_VERTEX_BIT) != 0) ? (" vertex") : ("")) 1811 << (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0) ? (" tess_control") : ("")) 1812 << (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0) ? (" tess_evaluation") : ("")) 1813 << (((m_stageFlags & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0) ? (" geometry") : ("")) 1814 << (((m_stageFlags & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0) ? (" fragment") : ("")) 1815 << " } stages.\n"; 1816 } 1817 1818 m_context.getTestContext().getLog() 1819 << tcu::TestLog::Message 1820 << msg.str() 1821 << tcu::TestLog::EndMessage; 1822 } 1823 1824 vk::VkPipelineLayout BufferRenderInstance::getPipelineLayout (void) const 1825 { 1826 return *m_pipelineLayout; 1827 } 1828 1829 void BufferRenderInstance::writeDrawCmdBuffer (vk::VkCommandBuffer cmd) const 1830 { 1831 // \note dynamic offset replaces the view offset, i.e. it is not offset relative to the view offset 1832 const deUint32 dynamicOffsets[] = 1833 { 1834 m_dynamicOffsetA, 1835 m_dynamicOffsetB, 1836 }; 1837 const deUint32 numOffsets = (!m_setDynamicOffset) ? (0u) : (getInterfaceNumResources(m_shaderInterface)); 1838 const deUint32* const dynamicOffsetPtr = (!m_setDynamicOffset) ? (DE_NULL) : (dynamicOffsets); 1839 1840 if (m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE && m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH) 1841 { 1842 m_vki.cmdBindDescriptorSets(cmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, getPipelineLayout(), 0, 1, &m_descriptorSet.get(), numOffsets, dynamicOffsetPtr); 1843 } 1844 else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE) 1845 { 1846 m_vki.cmdPushDescriptorSetWithTemplateKHR(cmd, *m_updateTemplate, getPipelineLayout(), 0, (const void*)m_updateRegistry.getRawPointer()); 1847 } 1848 else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH) 1849 { 1850 m_updateBuilder.updateWithPush(m_vki, cmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0); 1851 } 1852 1853 m_vki.cmdDraw(cmd, 6 * 4, 1, 0, 0); // render four quads (two separate triangles) 1854 } 1855 1856 tcu::TestStatus BufferRenderInstance::verifyResultImage (const tcu::ConstPixelBufferAccess& result) const 1857 { 1858 const tcu::Vec4 green (0.0f, 1.0f, 0.0f, 1.0f); 1859 const tcu::Vec4 yellow (1.0f, 1.0f, 0.0f, 1.0f); 1860 tcu::Surface reference (m_targetSize.x(), m_targetSize.y()); 1861 1862 drawQuadrantReferenceResult(reference.getAccess(), yellow, green, green, yellow); 1863 1864 if (!bilinearCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", reference.getAccess(), result, tcu::RGBA(1, 1, 1, 1), tcu::COMPARE_LOG_RESULT)) 1865 return tcu::TestStatus::fail("Image verification failed"); 1866 else 1867 return tcu::TestStatus::pass("Pass"); 1868 } 1869 1870 class ComputeInstanceResultBuffer 1871 { 1872 public: 1873 enum 1874 { 1875 DATA_SIZE = sizeof(tcu::Vec4[4]) 1876 }; 1877 1878 ComputeInstanceResultBuffer (const vk::DeviceInterface& vki, 1879 vk::VkDevice device, 1880 vk::Allocator& allocator); 1881 1882 void readResultContentsTo (tcu::Vec4 (*results)[4]) const; 1883 1884 inline vk::VkBuffer getBuffer (void) const { return *m_buffer; } 1885 inline const vk::VkBufferMemoryBarrier* getResultReadBarrier (void) const { return &m_bufferBarrier; } 1886 1887 private: 1888 static vk::Move<vk::VkBuffer> createResultBuffer (const vk::DeviceInterface& vki, 1889 vk::VkDevice device, 1890 vk::Allocator& allocator, 1891 de::MovePtr<vk::Allocation>* outAllocation); 1892 1893 static vk::VkBufferMemoryBarrier createResultBufferBarrier (vk::VkBuffer buffer); 1894 1895 const vk::DeviceInterface& m_vki; 1896 const vk::VkDevice m_device; 1897 1898 de::MovePtr<vk::Allocation> m_bufferMem; 1899 const vk::Unique<vk::VkBuffer> m_buffer; 1900 const vk::VkBufferMemoryBarrier m_bufferBarrier; 1901 }; 1902 1903 ComputeInstanceResultBuffer::ComputeInstanceResultBuffer (const vk::DeviceInterface& vki, 1904 vk::VkDevice device, 1905 vk::Allocator& allocator) 1906 : m_vki (vki) 1907 , m_device (device) 1908 , m_bufferMem (DE_NULL) 1909 , m_buffer (createResultBuffer(m_vki, m_device, allocator, &m_bufferMem)) 1910 , m_bufferBarrier (createResultBufferBarrier(*m_buffer)) 1911 { 1912 } 1913 1914 void ComputeInstanceResultBuffer::readResultContentsTo (tcu::Vec4 (*results)[4]) const 1915 { 1916 invalidateMappedMemoryRange(m_vki, m_device, m_bufferMem->getMemory(), m_bufferMem->getOffset(), sizeof(*results)); 1917 deMemcpy(*results, m_bufferMem->getHostPtr(), sizeof(*results)); 1918 } 1919 1920 vk::Move<vk::VkBuffer> ComputeInstanceResultBuffer::createResultBuffer (const vk::DeviceInterface& vki, 1921 vk::VkDevice device, 1922 vk::Allocator& allocator, 1923 de::MovePtr<vk::Allocation>* outAllocation) 1924 { 1925 const vk::VkBufferCreateInfo createInfo = 1926 { 1927 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, 1928 DE_NULL, 1929 0u, // flags 1930 (vk::VkDeviceSize)DATA_SIZE, // size 1931 vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, // usage 1932 vk::VK_SHARING_MODE_EXCLUSIVE, // sharingMode 1933 0u, // queueFamilyCount 1934 DE_NULL, // pQueueFamilyIndices 1935 }; 1936 vk::Move<vk::VkBuffer> buffer (vk::createBuffer(vki, device, &createInfo)); 1937 de::MovePtr<vk::Allocation> allocation (allocateAndBindObjectMemory(vki, device, allocator, *buffer, vk::MemoryRequirement::HostVisible)); 1938 const float clearValue = -1.0f; 1939 void* mapPtr = allocation->getHostPtr(); 1940 1941 for (size_t offset = 0; offset < DATA_SIZE; offset += sizeof(float)) 1942 deMemcpy(((deUint8*)mapPtr) + offset, &clearValue, sizeof(float)); 1943 1944 flushMappedMemoryRange(vki, device, allocation->getMemory(), allocation->getOffset(), (vk::VkDeviceSize)DATA_SIZE); 1945 1946 *outAllocation = allocation; 1947 return buffer; 1948 } 1949 1950 vk::VkBufferMemoryBarrier ComputeInstanceResultBuffer::createResultBufferBarrier (vk::VkBuffer buffer) 1951 { 1952 const vk::VkBufferMemoryBarrier bufferBarrier = 1953 { 1954 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 1955 DE_NULL, 1956 vk::VK_ACCESS_SHADER_WRITE_BIT, // outputMask 1957 vk::VK_ACCESS_HOST_READ_BIT, // inputMask 1958 VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex 1959 VK_QUEUE_FAMILY_IGNORED, // destQueueFamilyIndex 1960 buffer, // buffer 1961 (vk::VkDeviceSize)0u, // offset 1962 DATA_SIZE, // size 1963 }; 1964 return bufferBarrier; 1965 } 1966 1967 class ComputePipeline 1968 { 1969 public: 1970 ComputePipeline (const vk::DeviceInterface& vki, 1971 vk::VkDevice device, 1972 const vk::BinaryCollection& programCollection, 1973 deUint32 numDescriptorSets, 1974 const vk::VkDescriptorSetLayout* descriptorSetLayouts); 1975 1976 inline vk::VkPipeline getPipeline (void) const { return *m_pipeline; }; 1977 inline vk::VkPipelineLayout getPipelineLayout (void) const { return *m_pipelineLayout; }; 1978 1979 private: 1980 static vk::Move<vk::VkPipelineLayout> createPipelineLayout (const vk::DeviceInterface& vki, 1981 vk::VkDevice device, 1982 deUint32 numDescriptorSets, 1983 const vk::VkDescriptorSetLayout* descriptorSetLayouts); 1984 1985 static vk::Move<vk::VkPipeline> createPipeline (const vk::DeviceInterface& vki, 1986 vk::VkDevice device, 1987 const vk::BinaryCollection& programCollection, 1988 vk::VkPipelineLayout layout); 1989 1990 const vk::Unique<vk::VkPipelineLayout> m_pipelineLayout; 1991 const vk::Unique<vk::VkPipeline> m_pipeline; 1992 }; 1993 1994 ComputePipeline::ComputePipeline (const vk::DeviceInterface& vki, 1995 vk::VkDevice device, 1996 const vk::BinaryCollection& programCollection, 1997 deUint32 numDescriptorSets, 1998 const vk::VkDescriptorSetLayout* descriptorSetLayouts) 1999 : m_pipelineLayout (createPipelineLayout(vki, device, numDescriptorSets, descriptorSetLayouts)) 2000 , m_pipeline (createPipeline(vki, device, programCollection, *m_pipelineLayout)) 2001 { 2002 } 2003 2004 vk::Move<vk::VkPipelineLayout> ComputePipeline::createPipelineLayout (const vk::DeviceInterface& vki, 2005 vk::VkDevice device, 2006 deUint32 numDescriptorSets, 2007 const vk::VkDescriptorSetLayout* descriptorSetLayouts) 2008 { 2009 const vk::VkPipelineLayoutCreateInfo createInfo = 2010 { 2011 vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, 2012 DE_NULL, 2013 (vk::VkPipelineLayoutCreateFlags)0, 2014 numDescriptorSets, // descriptorSetCount 2015 descriptorSetLayouts, // pSetLayouts 2016 0u, // pushConstantRangeCount 2017 DE_NULL, // pPushConstantRanges 2018 }; 2019 return vk::createPipelineLayout(vki, device, &createInfo); 2020 } 2021 2022 vk::Move<vk::VkPipeline> ComputePipeline::createPipeline (const vk::DeviceInterface& vki, 2023 vk::VkDevice device, 2024 const vk::BinaryCollection& programCollection, 2025 vk::VkPipelineLayout layout) 2026 { 2027 const vk::Unique<vk::VkShaderModule> computeModule (vk::createShaderModule(vki, device, programCollection.get("compute"), (vk::VkShaderModuleCreateFlags)0u)); 2028 const vk::VkPipelineShaderStageCreateInfo cs = 2029 { 2030 vk::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, 2031 DE_NULL, 2032 (vk::VkPipelineShaderStageCreateFlags)0, 2033 vk::VK_SHADER_STAGE_COMPUTE_BIT, // stage 2034 *computeModule, // shader 2035 "main", 2036 DE_NULL, // pSpecializationInfo 2037 }; 2038 const vk::VkComputePipelineCreateInfo createInfo = 2039 { 2040 vk::VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, 2041 DE_NULL, 2042 0u, // flags 2043 cs, // cs 2044 layout, // layout 2045 (vk::VkPipeline)0, // basePipelineHandle 2046 0u, // basePipelineIndex 2047 }; 2048 return createComputePipeline(vki, device, (vk::VkPipelineCache)0u, &createInfo); 2049 } 2050 2051 class ComputeCommand 2052 { 2053 public: 2054 ComputeCommand (const vk::DeviceInterface& vki, 2055 vk::VkDevice device, 2056 vk::VkPipeline pipeline, 2057 vk::VkPipelineLayout pipelineLayout, 2058 const tcu::UVec3& numWorkGroups, 2059 int numDescriptorSets, 2060 const vk::VkDescriptorSet* descriptorSets, 2061 int numDynamicOffsets, 2062 const deUint32* dynamicOffsets, 2063 int numPreBarriers, 2064 const vk::VkBufferMemoryBarrier* preBarriers, 2065 int numPostBarriers, 2066 const vk::VkBufferMemoryBarrier* postBarriers); 2067 2068 void submitAndWait (deUint32 queueFamilyIndex, vk::VkQueue queue, vk::VkDescriptorUpdateTemplateKHR updateTemplate = DE_NULL, const void *rawUpdateData = 0) const; 2069 void submitAndWait (deUint32 queueFamilyIndex, vk::VkQueue queue, vk::DescriptorSetUpdateBuilder& updateBuilder) const; 2070 2071 private: 2072 const vk::DeviceInterface& m_vki; 2073 const vk::VkDevice m_device; 2074 const vk::VkPipeline m_pipeline; 2075 const vk::VkPipelineLayout m_pipelineLayout; 2076 const tcu::UVec3 m_numWorkGroups; 2077 const int m_numDescriptorSets; 2078 const vk::VkDescriptorSet* const m_descriptorSets; 2079 const int m_numDynamicOffsets; 2080 const deUint32* const m_dynamicOffsets; 2081 const int m_numPreBarriers; 2082 const vk::VkBufferMemoryBarrier* const m_preBarriers; 2083 const int m_numPostBarriers; 2084 const vk::VkBufferMemoryBarrier* const m_postBarriers; 2085 }; 2086 2087 ComputeCommand::ComputeCommand (const vk::DeviceInterface& vki, 2088 vk::VkDevice device, 2089 vk::VkPipeline pipeline, 2090 vk::VkPipelineLayout pipelineLayout, 2091 const tcu::UVec3& numWorkGroups, 2092 int numDescriptorSets, 2093 const vk::VkDescriptorSet* descriptorSets, 2094 int numDynamicOffsets, 2095 const deUint32* dynamicOffsets, 2096 int numPreBarriers, 2097 const vk::VkBufferMemoryBarrier* preBarriers, 2098 int numPostBarriers, 2099 const vk::VkBufferMemoryBarrier* postBarriers) 2100 : m_vki (vki) 2101 , m_device (device) 2102 , m_pipeline (pipeline) 2103 , m_pipelineLayout (pipelineLayout) 2104 , m_numWorkGroups (numWorkGroups) 2105 , m_numDescriptorSets (numDescriptorSets) 2106 , m_descriptorSets (descriptorSets) 2107 , m_numDynamicOffsets (numDynamicOffsets) 2108 , m_dynamicOffsets (dynamicOffsets) 2109 , m_numPreBarriers (numPreBarriers) 2110 , m_preBarriers (preBarriers) 2111 , m_numPostBarriers (numPostBarriers) 2112 , m_postBarriers (postBarriers) 2113 { 2114 } 2115 2116 void ComputeCommand::submitAndWait (deUint32 queueFamilyIndex, vk::VkQueue queue, vk::VkDescriptorUpdateTemplateKHR updateTemplate, const void *rawUpdateData) const 2117 { 2118 const vk::VkCommandPoolCreateInfo cmdPoolCreateInfo = 2119 { 2120 vk::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, 2121 DE_NULL, 2122 vk::VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, // flags 2123 queueFamilyIndex, // queueFamilyIndex 2124 }; 2125 const vk::Unique<vk::VkCommandPool> cmdPool (vk::createCommandPool(m_vki, m_device, &cmdPoolCreateInfo)); 2126 2127 const vk::VkFenceCreateInfo fenceCreateInfo = 2128 { 2129 vk::VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, 2130 DE_NULL, 2131 0u, // flags 2132 }; 2133 2134 const vk::VkCommandBufferAllocateInfo cmdBufCreateInfo = 2135 { 2136 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, 2137 DE_NULL, 2138 *cmdPool, // cmdPool 2139 vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY, // level 2140 1u, // count 2141 }; 2142 const vk::VkCommandBufferBeginInfo cmdBufBeginInfo = 2143 { 2144 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 2145 DE_NULL, 2146 vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, // flags 2147 (const vk::VkCommandBufferInheritanceInfo*)DE_NULL, 2148 }; 2149 2150 const vk::Unique<vk::VkFence> cmdCompleteFence (vk::createFence(m_vki, m_device, &fenceCreateInfo)); 2151 const vk::Unique<vk::VkCommandBuffer> cmd (vk::allocateCommandBuffer(m_vki, m_device, &cmdBufCreateInfo)); 2152 const deUint64 infiniteTimeout = ~(deUint64)0u; 2153 2154 VK_CHECK(m_vki.beginCommandBuffer(*cmd, &cmdBufBeginInfo)); 2155 2156 m_vki.cmdBindPipeline(*cmd, vk::VK_PIPELINE_BIND_POINT_COMPUTE, m_pipeline); 2157 2158 if (m_numDescriptorSets) 2159 { 2160 m_vki.cmdBindDescriptorSets(*cmd, vk::VK_PIPELINE_BIND_POINT_COMPUTE, m_pipelineLayout, 0, m_numDescriptorSets, m_descriptorSets, m_numDynamicOffsets, m_dynamicOffsets); 2161 } 2162 2163 if (updateTemplate != DE_NULL) 2164 { 2165 // we need to update the push descriptors 2166 m_vki.cmdPushDescriptorSetWithTemplateKHR(*cmd, updateTemplate, m_pipelineLayout, 0, rawUpdateData); 2167 } 2168 2169 if (m_numPreBarriers) 2170 m_vki.cmdPipelineBarrier(*cmd, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, (vk::VkDependencyFlags)0, 2171 0, (const vk::VkMemoryBarrier*)DE_NULL, 2172 m_numPreBarriers, m_preBarriers, 2173 0, (const vk::VkImageMemoryBarrier*)DE_NULL); 2174 2175 m_vki.cmdDispatch(*cmd, m_numWorkGroups.x(), m_numWorkGroups.y(), m_numWorkGroups.z()); 2176 m_vki.cmdPipelineBarrier(*cmd, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (vk::VkDependencyFlags)0, 2177 0, (const vk::VkMemoryBarrier*)DE_NULL, 2178 m_numPostBarriers, m_postBarriers, 2179 0, (const vk::VkImageMemoryBarrier*)DE_NULL); 2180 VK_CHECK(m_vki.endCommandBuffer(*cmd)); 2181 2182 // run 2183 { 2184 const vk::VkSubmitInfo submitInfo = 2185 { 2186 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO, 2187 DE_NULL, 2188 0u, 2189 (const vk::VkSemaphore*)0, 2190 (const vk::VkPipelineStageFlags*)DE_NULL, 2191 1u, 2192 &cmd.get(), 2193 0u, 2194 (const vk::VkSemaphore*)0, 2195 }; 2196 VK_CHECK(m_vki.queueSubmit(queue, 1, &submitInfo, *cmdCompleteFence)); 2197 } 2198 VK_CHECK(m_vki.waitForFences(m_device, 1, &cmdCompleteFence.get(), 0u, infiniteTimeout)); // \note: timeout is failure 2199 } 2200 2201 //cmdPushDescriptorSet variant 2202 void ComputeCommand::submitAndWait (deUint32 queueFamilyIndex, vk::VkQueue queue, vk::DescriptorSetUpdateBuilder& updateBuilder) const 2203 { 2204 const vk::VkCommandPoolCreateInfo cmdPoolCreateInfo = 2205 { 2206 vk::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, 2207 DE_NULL, 2208 vk::VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, // flags 2209 queueFamilyIndex, // queueFamilyIndex 2210 }; 2211 const vk::Unique<vk::VkCommandPool> cmdPool (vk::createCommandPool(m_vki, m_device, &cmdPoolCreateInfo)); 2212 2213 const vk::VkFenceCreateInfo fenceCreateInfo = 2214 { 2215 vk::VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, 2216 DE_NULL, 2217 0u, // flags 2218 }; 2219 2220 const vk::VkCommandBufferAllocateInfo cmdBufCreateInfo = 2221 { 2222 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, 2223 DE_NULL, 2224 *cmdPool, // cmdPool 2225 vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY, // level 2226 1u, // count 2227 }; 2228 const vk::VkCommandBufferBeginInfo cmdBufBeginInfo = 2229 { 2230 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 2231 DE_NULL, 2232 vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, // flags 2233 (const vk::VkCommandBufferInheritanceInfo*)DE_NULL, 2234 }; 2235 2236 const vk::Unique<vk::VkFence> cmdCompleteFence (vk::createFence(m_vki, m_device, &fenceCreateInfo)); 2237 const vk::Unique<vk::VkCommandBuffer> cmd (vk::allocateCommandBuffer(m_vki, m_device, &cmdBufCreateInfo)); 2238 const deUint64 infiniteTimeout = ~(deUint64)0u; 2239 2240 VK_CHECK(m_vki.beginCommandBuffer(*cmd, &cmdBufBeginInfo)); 2241 2242 m_vki.cmdBindPipeline(*cmd, vk::VK_PIPELINE_BIND_POINT_COMPUTE, m_pipeline); 2243 2244 if (m_numDescriptorSets) 2245 { 2246 m_vki.cmdBindDescriptorSets(*cmd, vk::VK_PIPELINE_BIND_POINT_COMPUTE, m_pipelineLayout, 0, m_numDescriptorSets, m_descriptorSets, m_numDynamicOffsets, m_dynamicOffsets); 2247 } 2248 2249 updateBuilder.updateWithPush(m_vki, *cmd, vk::VK_PIPELINE_BIND_POINT_COMPUTE, m_pipelineLayout, 0); 2250 2251 if (m_numPreBarriers) 2252 m_vki.cmdPipelineBarrier(*cmd, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, (vk::VkDependencyFlags)0, 2253 0, (const vk::VkMemoryBarrier*)DE_NULL, 2254 m_numPreBarriers, m_preBarriers, 2255 0, (const vk::VkImageMemoryBarrier*)DE_NULL); 2256 2257 m_vki.cmdDispatch(*cmd, m_numWorkGroups.x(), m_numWorkGroups.y(), m_numWorkGroups.z()); 2258 m_vki.cmdPipelineBarrier(*cmd, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (vk::VkDependencyFlags)0, 2259 0, (const vk::VkMemoryBarrier*)DE_NULL, 2260 m_numPostBarriers, m_postBarriers, 2261 0, (const vk::VkImageMemoryBarrier*)DE_NULL); 2262 VK_CHECK(m_vki.endCommandBuffer(*cmd)); 2263 2264 // run 2265 { 2266 const vk::VkSubmitInfo submitInfo = 2267 { 2268 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO, 2269 DE_NULL, 2270 0u, 2271 (const vk::VkSemaphore*)0, 2272 (const vk::VkPipelineStageFlags*)DE_NULL, 2273 1u, 2274 &cmd.get(), 2275 0u, 2276 (const vk::VkSemaphore*)0, 2277 }; 2278 VK_CHECK(m_vki.queueSubmit(queue, 1, &submitInfo, *cmdCompleteFence)); 2279 } 2280 VK_CHECK(m_vki.waitForFences(m_device, 1, &cmdCompleteFence.get(), 0u, infiniteTimeout)); // \note: timeout is failure 2281 } 2282 2283 class BufferComputeInstance : public vkt::TestInstance 2284 { 2285 public: 2286 BufferComputeInstance (Context& context, 2287 DescriptorUpdateMethod updateMethod, 2288 vk::VkDescriptorType descriptorType, 2289 ShaderInputInterface shaderInterface, 2290 bool viewOffset, 2291 bool dynamicOffset, 2292 bool dynamicOffsetNonZero); 2293 2294 private: 2295 vk::Move<vk::VkBuffer> createColorDataBuffer (deUint32 offset, deUint32 bufferSize, const tcu::Vec4& value1, const tcu::Vec4& value2, de::MovePtr<vk::Allocation>* outAllocation); 2296 vk::Move<vk::VkBufferView> createBufferView (vk::VkBuffer buffer, deUint32 offset) const; 2297 vk::Move<vk::VkDescriptorSetLayout> createDescriptorSetLayout (void) const; 2298 vk::Move<vk::VkDescriptorPool> createDescriptorPool (void) const; 2299 vk::Move<vk::VkDescriptorSet> createDescriptorSet (vk::VkDescriptorPool pool, vk::VkDescriptorSetLayout layout, vk::VkBuffer viewA, deUint32 offsetA, vk::VkBuffer viewB, deUint32 offsetB, vk::VkBuffer resBuf); 2300 void writeDescriptorSet (vk::VkDescriptorSet descriptorSet, vk::VkBuffer viewA, deUint32 offsetA, vk::VkBuffer viewB, deUint32 offsetB, vk::VkBuffer resBuf); 2301 void writeDescriptorSetWithTemplate (vk::VkDescriptorSet descriptorSet, vk::VkDescriptorSetLayout layout, vk::VkBuffer viewA, deUint32 offsetA, vk::VkBuffer viewB, deUint32 offsetB, vk::VkBuffer resBuf, bool withPush = false, vk::VkPipelineLayout pipelineLayout = DE_NULL); 2302 2303 tcu::TestStatus iterate (void); 2304 void logTestPlan (void) const; 2305 tcu::TestStatus testResourceAccess (void); 2306 2307 enum 2308 { 2309 STATIC_OFFSET_VALUE_A = 256, 2310 DYNAMIC_OFFSET_VALUE_A = 512, 2311 STATIC_OFFSET_VALUE_B = 1024, 2312 DYNAMIC_OFFSET_VALUE_B = 768, 2313 }; 2314 2315 const DescriptorUpdateMethod m_updateMethod; 2316 const vk::VkDescriptorType m_descriptorType; 2317 const ShaderInputInterface m_shaderInterface; 2318 const bool m_setViewOffset; 2319 const bool m_setDynamicOffset; 2320 const bool m_dynamicOffsetNonZero; 2321 2322 vk::Move<vk::VkDescriptorUpdateTemplateKHR> m_updateTemplate; 2323 const vk::DeviceInterface& m_vki; 2324 const vk::VkDevice m_device; 2325 const vk::VkQueue m_queue; 2326 const deUint32 m_queueFamilyIndex; 2327 vk::Allocator& m_allocator; 2328 2329 const ComputeInstanceResultBuffer m_result; 2330 2331 RawUpdateRegistry m_updateRegistry; 2332 vk::DescriptorSetUpdateBuilder m_updateBuilder; 2333 }; 2334 2335 BufferComputeInstance::BufferComputeInstance (Context& context, 2336 DescriptorUpdateMethod updateMethod, 2337 vk::VkDescriptorType descriptorType, 2338 ShaderInputInterface shaderInterface, 2339 bool viewOffset, 2340 bool dynamicOffset, 2341 bool dynamicOffsetNonZero) 2342 : vkt::TestInstance (context) 2343 , m_updateMethod (updateMethod) 2344 , m_descriptorType (descriptorType) 2345 , m_shaderInterface (shaderInterface) 2346 , m_setViewOffset (viewOffset) 2347 , m_setDynamicOffset (dynamicOffset) 2348 , m_dynamicOffsetNonZero (dynamicOffsetNonZero) 2349 , m_updateTemplate () 2350 , m_vki (context.getDeviceInterface()) 2351 , m_device (context.getDevice()) 2352 , m_queue (context.getUniversalQueue()) 2353 , m_queueFamilyIndex (context.getUniversalQueueFamilyIndex()) 2354 , m_allocator (context.getDefaultAllocator()) 2355 , m_result (m_vki, m_device, m_allocator) 2356 , m_updateRegistry () 2357 , m_updateBuilder () 2358 { 2359 if (m_dynamicOffsetNonZero) 2360 DE_ASSERT(m_setDynamicOffset); 2361 } 2362 2363 vk::Move<vk::VkBuffer> BufferComputeInstance::createColorDataBuffer (deUint32 offset, deUint32 bufferSize, const tcu::Vec4& value1, const tcu::Vec4& value2, de::MovePtr<vk::Allocation>* outAllocation) 2364 { 2365 DE_ASSERT(offset + sizeof(tcu::Vec4[2]) <= bufferSize); 2366 2367 const bool isUniformBuffer = isUniformDescriptorType(m_descriptorType); 2368 const vk::VkBufferUsageFlags usageFlags = (isUniformBuffer) ? (vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) : (vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT); 2369 const vk::VkBufferCreateInfo createInfo = 2370 { 2371 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, 2372 DE_NULL, 2373 0u, // flags 2374 (vk::VkDeviceSize)bufferSize, // size 2375 usageFlags, // usage 2376 vk::VK_SHARING_MODE_EXCLUSIVE, // sharingMode 2377 0u, // queueFamilyCount 2378 DE_NULL, // pQueueFamilyIndices 2379 }; 2380 vk::Move<vk::VkBuffer> buffer (vk::createBuffer(m_vki, m_device, &createInfo)); 2381 de::MovePtr<vk::Allocation> allocation (allocateAndBindObjectMemory(m_vki, m_device, m_allocator, *buffer, vk::MemoryRequirement::HostVisible)); 2382 void* mapPtr = allocation->getHostPtr(); 2383 2384 if (offset) 2385 deMemset(mapPtr, 0x5A, (size_t)offset); 2386 deMemcpy((deUint8*)mapPtr + offset, value1.getPtr(), sizeof(tcu::Vec4)); 2387 deMemcpy((deUint8*)mapPtr + offset + sizeof(tcu::Vec4), value2.getPtr(), sizeof(tcu::Vec4)); 2388 deMemset((deUint8*)mapPtr + offset + 2 * sizeof(tcu::Vec4), 0x5A, (size_t)bufferSize - (size_t)offset - 2 * sizeof(tcu::Vec4)); 2389 2390 flushMappedMemoryRange(m_vki, m_device, allocation->getMemory(), allocation->getOffset(), bufferSize); 2391 2392 *outAllocation = allocation; 2393 return buffer; 2394 } 2395 2396 vk::Move<vk::VkDescriptorSetLayout> BufferComputeInstance::createDescriptorSetLayout (void) const 2397 { 2398 vk::DescriptorSetLayoutBuilder builder; 2399 vk::VkDescriptorSetLayoutCreateFlags extraFlags = 0; 2400 2401 if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE || 2402 m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH) 2403 { 2404 extraFlags |= vk::VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR; 2405 } 2406 2407 builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT); 2408 2409 switch (m_shaderInterface) 2410 { 2411 case SHADER_INPUT_SINGLE_DESCRIPTOR: 2412 builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT); 2413 break; 2414 2415 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS: 2416 builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT); 2417 builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT); 2418 break; 2419 2420 case SHADER_INPUT_DESCRIPTOR_ARRAY: 2421 builder.addArrayBinding(m_descriptorType, 2u, vk::VK_SHADER_STAGE_COMPUTE_BIT); 2422 break; 2423 2424 default: 2425 DE_FATAL("Impossible"); 2426 }; 2427 2428 return builder.build(m_vki, m_device, extraFlags); 2429 } 2430 2431 vk::Move<vk::VkDescriptorPool> BufferComputeInstance::createDescriptorPool (void) const 2432 { 2433 return vk::DescriptorPoolBuilder() 2434 .addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER) 2435 .addType(m_descriptorType, getInterfaceNumResources(m_shaderInterface)) 2436 .build(m_vki, m_device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1); 2437 } 2438 2439 vk::Move<vk::VkDescriptorSet> BufferComputeInstance::createDescriptorSet (vk::VkDescriptorPool pool, vk::VkDescriptorSetLayout layout, vk::VkBuffer viewA, deUint32 offsetA, vk::VkBuffer viewB, deUint32 offsetB, vk::VkBuffer resBuf) 2440 { 2441 const vk::VkDescriptorSetAllocateInfo allocInfo = 2442 { 2443 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, 2444 DE_NULL, 2445 pool, 2446 1u, 2447 &layout 2448 }; 2449 2450 vk::Move<vk::VkDescriptorSet> descriptorSet; 2451 if (m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH && m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE) 2452 { 2453 descriptorSet = allocateDescriptorSet(m_vki, m_device, &allocInfo); 2454 } 2455 else 2456 { 2457 descriptorSet = vk::Move<vk::VkDescriptorSet>(); 2458 } 2459 2460 if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_TEMPLATE) 2461 { 2462 writeDescriptorSetWithTemplate(*descriptorSet, layout, viewA, offsetA, viewB, offsetB, resBuf); 2463 } 2464 else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL) 2465 { 2466 writeDescriptorSet(*descriptorSet, viewA, offsetA, viewB, offsetB, resBuf); 2467 } 2468 2469 return descriptorSet; 2470 } 2471 2472 void BufferComputeInstance::writeDescriptorSet (vk::VkDescriptorSet descriptorSet, vk::VkBuffer viewA, deUint32 offsetA, vk::VkBuffer viewB, deUint32 offsetB, vk::VkBuffer resBuf) 2473 { 2474 const vk::VkDescriptorBufferInfo resultInfo = vk::makeDescriptorBufferInfo(resBuf, 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE); 2475 const vk::VkDescriptorBufferInfo bufferInfos[2] = 2476 { 2477 vk::makeDescriptorBufferInfo(viewA, (vk::VkDeviceSize)offsetA, (vk::VkDeviceSize)sizeof(tcu::Vec4[2])), 2478 vk::makeDescriptorBufferInfo(viewB, (vk::VkDeviceSize)offsetB, (vk::VkDeviceSize)sizeof(tcu::Vec4[2])), 2479 }; 2480 2481 // result 2482 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultInfo); 2483 2484 // buffers 2485 switch (m_shaderInterface) 2486 { 2487 case SHADER_INPUT_SINGLE_DESCRIPTOR: 2488 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), m_descriptorType, &bufferInfos[0]); 2489 break; 2490 2491 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS: 2492 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), m_descriptorType, &bufferInfos[0]); 2493 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), m_descriptorType, &bufferInfos[1]); 2494 break; 2495 2496 case SHADER_INPUT_DESCRIPTOR_ARRAY: 2497 m_updateBuilder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), m_descriptorType, 2u, bufferInfos); 2498 break; 2499 2500 default: 2501 DE_FATAL("Impossible"); 2502 } 2503 2504 if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL) 2505 { 2506 m_updateBuilder.update(m_vki, m_device); 2507 } 2508 } 2509 2510 void BufferComputeInstance::writeDescriptorSetWithTemplate (vk::VkDescriptorSet descriptorSet, vk::VkDescriptorSetLayout layout, vk::VkBuffer viewA, deUint32 offsetA, vk::VkBuffer viewB, deUint32 offsetB, vk::VkBuffer resBuf, bool withPush, vk::VkPipelineLayout pipelineLayout) 2511 { 2512 const vk::VkDescriptorBufferInfo resultInfo = vk::makeDescriptorBufferInfo(resBuf, 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE); 2513 const vk::VkDescriptorBufferInfo bufferInfos[2] = 2514 { 2515 vk::makeDescriptorBufferInfo(viewA, (vk::VkDeviceSize)offsetA, (vk::VkDeviceSize)sizeof(tcu::Vec4[2])), 2516 vk::makeDescriptorBufferInfo(viewB, (vk::VkDeviceSize)offsetB, (vk::VkDeviceSize)sizeof(tcu::Vec4[2])), 2517 }; 2518 std::vector<vk::VkDescriptorUpdateTemplateEntryKHR> updateEntries; 2519 vk::VkDescriptorUpdateTemplateCreateInfoKHR templateCreateInfo = 2520 { 2521 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR, 2522 DE_NULL, 2523 0, 2524 0, // descriptorUpdateEntryCount 2525 DE_NULL, // pDescriptorUpdateEntries 2526 withPush ? vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR : vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR, 2527 layout, 2528 vk::VK_PIPELINE_BIND_POINT_COMPUTE, 2529 pipelineLayout, 2530 0 2531 }; 2532 m_updateRegistry.addWriteObject(resultInfo); 2533 m_updateRegistry.addWriteObject(bufferInfos[0]); 2534 m_updateRegistry.addWriteObject(bufferInfos[1]); 2535 2536 // result 2537 updateEntries.push_back(createTemplateBinding(0, 0, 1, vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, m_updateRegistry.getWriteObjectOffset(0), 0)); 2538 2539 // buffers 2540 switch (m_shaderInterface) 2541 { 2542 case SHADER_INPUT_SINGLE_DESCRIPTOR: 2543 updateEntries.push_back(createTemplateBinding(1, 0, 1, m_descriptorType, m_updateRegistry.getWriteObjectOffset(1), 0)); 2544 break; 2545 2546 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS: 2547 updateEntries.push_back(createTemplateBinding(1, 0, 1, m_descriptorType, m_updateRegistry.getWriteObjectOffset(1), 0)); 2548 updateEntries.push_back(createTemplateBinding(2, 0, 1, m_descriptorType, m_updateRegistry.getWriteObjectOffset(2), 0)); 2549 break; 2550 2551 case SHADER_INPUT_DESCRIPTOR_ARRAY: 2552 updateEntries.push_back(createTemplateBinding(1, 0, 2, m_descriptorType, m_updateRegistry.getWriteObjectOffset(1), sizeof(bufferInfos[0]))); 2553 break; 2554 2555 default: 2556 DE_FATAL("Impossible"); 2557 } 2558 2559 templateCreateInfo.pDescriptorUpdateEntries = &updateEntries[0]; 2560 templateCreateInfo.descriptorUpdateEntryCount = (deUint32)updateEntries.size(); 2561 2562 m_updateTemplate = vk::createDescriptorUpdateTemplateKHR(m_vki, m_device, &templateCreateInfo); 2563 2564 if (!withPush) 2565 { 2566 m_vki.updateDescriptorSetWithTemplateKHR(m_device, descriptorSet, *m_updateTemplate, m_updateRegistry.getRawPointer()); 2567 } 2568 } 2569 2570 tcu::TestStatus BufferComputeInstance::iterate (void) 2571 { 2572 logTestPlan(); 2573 return testResourceAccess(); 2574 } 2575 2576 void BufferComputeInstance::logTestPlan (void) const 2577 { 2578 std::ostringstream msg; 2579 2580 msg << "Accessing resource in a compute program.\n" 2581 << "Single descriptor set. Descriptor set contains " 2582 << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" : 2583 (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? "two" : 2584 (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" : 2585 (const char*)DE_NULL) 2586 << " source descriptor(s) of type " << vk::getDescriptorTypeName(m_descriptorType) 2587 << " and one destination VK_DESCRIPTOR_TYPE_STORAGE_BUFFER to store results to.\n" 2588 << "Source descriptor buffer view(s) have " << ((m_setViewOffset) ? ("non-") : ("")) << "zero offset.\n"; 2589 2590 if (isDynamicDescriptorType(m_descriptorType)) 2591 { 2592 if (m_setDynamicOffset) 2593 { 2594 msg << "Source buffer(s) are given a dynamic offset at bind time.\n" 2595 << "The supplied dynamic offset is " << ((m_dynamicOffsetNonZero) ? ("non-") : ("")) << "zero.\n"; 2596 } 2597 else 2598 { 2599 msg << "Dynamic offset is not supplied at bind time. Expecting bind to offset 0.\n"; 2600 } 2601 } 2602 2603 msg << "Destination buffer is pre-initialized to -1.\n"; 2604 2605 m_context.getTestContext().getLog() 2606 << tcu::TestLog::Message 2607 << msg.str() 2608 << tcu::TestLog::EndMessage; 2609 } 2610 2611 tcu::TestStatus BufferComputeInstance::testResourceAccess (void) 2612 { 2613 enum 2614 { 2615 ADDRESSABLE_SIZE = 256, // allocate a lot more than required 2616 }; 2617 2618 const bool isDynamicCase = isDynamicDescriptorType(m_descriptorType); 2619 const bool isUniformBuffer = isUniformDescriptorType(m_descriptorType); 2620 const deUint32 bindTimeOffsets[] = 2621 { 2622 (m_dynamicOffsetNonZero) ? ((deUint32)DYNAMIC_OFFSET_VALUE_A) : (0u), 2623 (m_dynamicOffsetNonZero) ? ((deUint32)DYNAMIC_OFFSET_VALUE_B) : (0u), 2624 }; 2625 2626 const tcu::Vec4 colorA1 = tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f); 2627 const tcu::Vec4 colorA2 = tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f); 2628 const tcu::Vec4 colorB1 = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f); 2629 const tcu::Vec4 colorB2 = tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f); 2630 2631 const deUint32 dataOffsetA = ((isDynamicCase) ? (bindTimeOffsets[0]) : 0) + ((m_setViewOffset) ? ((deUint32)STATIC_OFFSET_VALUE_A) : (0u)); 2632 const deUint32 dataOffsetB = ((isDynamicCase) ? (bindTimeOffsets[1]) : 0) + ((m_setViewOffset) ? ((deUint32)STATIC_OFFSET_VALUE_B) : (0u)); 2633 const deUint32 viewOffsetA = (m_setViewOffset) ? ((deUint32)STATIC_OFFSET_VALUE_A) : (0u); 2634 const deUint32 viewOffsetB = (m_setViewOffset) ? ((deUint32)STATIC_OFFSET_VALUE_B) : (0u); 2635 const deUint32 bufferSizeA = dataOffsetA + ADDRESSABLE_SIZE; 2636 const deUint32 bufferSizeB = dataOffsetB + ADDRESSABLE_SIZE; 2637 2638 de::MovePtr<vk::Allocation> bufferMemA; 2639 const vk::Unique<vk::VkBuffer> bufferA (createColorDataBuffer(dataOffsetA, bufferSizeA, colorA1, colorA2, &bufferMemA)); 2640 2641 de::MovePtr<vk::Allocation> bufferMemB; 2642 const vk::Unique<vk::VkBuffer> bufferB ((getInterfaceNumResources(m_shaderInterface) == 1u) 2643 ? (vk::Move<vk::VkBuffer>()) 2644 : (createColorDataBuffer(dataOffsetB, bufferSizeB, colorB1, colorB2, &bufferMemB))); 2645 2646 const vk::Unique<vk::VkDescriptorSetLayout> descriptorSetLayout (createDescriptorSetLayout()); 2647 const vk::Unique<vk::VkDescriptorPool> descriptorPool (createDescriptorPool()); 2648 const vk::Unique<vk::VkDescriptorSet> descriptorSet (createDescriptorSet(*descriptorPool, *descriptorSetLayout, *bufferA, viewOffsetA, *bufferB, viewOffsetB, m_result.getBuffer())); 2649 const ComputePipeline pipeline (m_vki, m_device, m_context.getBinaryCollection(), 1, &descriptorSetLayout.get()); 2650 2651 const vk::VkAccessFlags inputBit = (isUniformBuffer) ? (vk::VK_ACCESS_UNIFORM_READ_BIT) : (vk::VK_ACCESS_SHADER_READ_BIT); 2652 const vk::VkBufferMemoryBarrier bufferBarriers[] = 2653 { 2654 { 2655 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 2656 DE_NULL, 2657 vk::VK_ACCESS_HOST_WRITE_BIT, // outputMask 2658 inputBit, // inputMask 2659 VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex 2660 VK_QUEUE_FAMILY_IGNORED, // destQueueFamilyIndex 2661 *bufferA, // buffer 2662 (vk::VkDeviceSize)0u, // offset 2663 (vk::VkDeviceSize)bufferSizeA, // size 2664 }, 2665 { 2666 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 2667 DE_NULL, 2668 vk::VK_ACCESS_HOST_WRITE_BIT, // outputMask 2669 inputBit, // inputMask 2670 VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex 2671 VK_QUEUE_FAMILY_IGNORED, // destQueueFamilyIndex 2672 *bufferB, // buffer 2673 (vk::VkDeviceSize)0u, // offset 2674 (vk::VkDeviceSize)bufferSizeB, // size 2675 } 2676 }; 2677 2678 const deUint32 numSrcBuffers = getInterfaceNumResources(m_shaderInterface); 2679 2680 const vk::VkDescriptorSet descriptorSets[] = { *descriptorSet }; 2681 const int numDescriptorSets = (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE || m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH) ? 0 : DE_LENGTH_OF_ARRAY(descriptorSets); 2682 const deUint32* const dynamicOffsets = (m_setDynamicOffset) ? (bindTimeOffsets) : (DE_NULL); 2683 const deUint32 numDynamicOffsets = (m_setDynamicOffset) ? (numSrcBuffers) : (0); 2684 const vk::VkBufferMemoryBarrier* const preBarriers = bufferBarriers; 2685 const int numPreBarriers = numSrcBuffers; 2686 const vk::VkBufferMemoryBarrier* const postBarriers = m_result.getResultReadBarrier(); 2687 const int numPostBarriers = 1; 2688 2689 const ComputeCommand compute (m_vki, 2690 m_device, 2691 pipeline.getPipeline(), 2692 pipeline.getPipelineLayout(), 2693 tcu::UVec3(4, 1, 1), 2694 numDescriptorSets, descriptorSets, 2695 numDynamicOffsets, dynamicOffsets, 2696 numPreBarriers, preBarriers, 2697 numPostBarriers, postBarriers); 2698 2699 const tcu::Vec4 refQuadrantValue14 = (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? (colorA2) : 2700 (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? (colorB2) : 2701 (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? (colorB2) : 2702 (tcu::Vec4(-2.0f)); 2703 const tcu::Vec4 refQuadrantValue23 = (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? (colorA1) : 2704 (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? (colorA1) : 2705 (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? (colorA1) : 2706 (tcu::Vec4(-2.0f)); 2707 const tcu::Vec4 references[4] = 2708 { 2709 refQuadrantValue14, 2710 refQuadrantValue23, 2711 refQuadrantValue23, 2712 refQuadrantValue14, 2713 }; 2714 tcu::Vec4 results[4]; 2715 2716 if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE) 2717 { 2718 writeDescriptorSetWithTemplate(DE_NULL, *descriptorSetLayout, *bufferA, viewOffsetA, *bufferB, viewOffsetB, m_result.getBuffer(), true, pipeline.getPipelineLayout()); 2719 compute.submitAndWait(m_queueFamilyIndex, m_queue, *m_updateTemplate, (const void*) m_updateRegistry.getRawPointer()); 2720 } 2721 else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH) 2722 { 2723 writeDescriptorSet(DE_NULL, *bufferA, viewOffsetA, *bufferB, viewOffsetB, m_result.getBuffer()); 2724 compute.submitAndWait(m_queueFamilyIndex, m_queue, m_updateBuilder); 2725 } 2726 else 2727 { 2728 compute.submitAndWait(m_queueFamilyIndex, m_queue); 2729 } 2730 m_result.readResultContentsTo(&results); 2731 2732 // verify 2733 if (results[0] == references[0] && 2734 results[1] == references[1] && 2735 results[2] == references[2] && 2736 results[3] == references[3]) 2737 { 2738 return tcu::TestStatus::pass("Pass"); 2739 } 2740 else if (results[0] == tcu::Vec4(-1.0f) && 2741 results[1] == tcu::Vec4(-1.0f) && 2742 results[2] == tcu::Vec4(-1.0f) && 2743 results[3] == tcu::Vec4(-1.0f)) 2744 { 2745 m_context.getTestContext().getLog() 2746 << tcu::TestLog::Message 2747 << "Result buffer was not written to." 2748 << tcu::TestLog::EndMessage; 2749 return tcu::TestStatus::fail("Result buffer was not written to"); 2750 } 2751 else 2752 { 2753 m_context.getTestContext().getLog() 2754 << tcu::TestLog::Message 2755 << "Error expected [" 2756 << references[0] << ", " 2757 << references[1] << ", " 2758 << references[2] << ", " 2759 << references[3] << "], got [" 2760 << results[0] << ", " 2761 << results[1] << ", " 2762 << results[2] << ", " 2763 << results[3] << "]" 2764 << tcu::TestLog::EndMessage; 2765 return tcu::TestStatus::fail("Invalid result values"); 2766 } 2767 } 2768 2769 class QuadrantRendederCase : public vkt::TestCase 2770 { 2771 public: 2772 QuadrantRendederCase (tcu::TestContext& testCtx, 2773 const char* name, 2774 const char* description, 2775 glu::GLSLVersion glslVersion, 2776 vk::VkShaderStageFlags exitingStages, 2777 vk::VkShaderStageFlags activeStages); 2778 private: 2779 virtual std::string genExtensionDeclarations (vk::VkShaderStageFlagBits stage) const = 0; 2780 virtual std::string genResourceDeclarations (vk::VkShaderStageFlagBits stage, int numUsedBindings) const = 0; 2781 virtual std::string genResourceAccessSource (vk::VkShaderStageFlagBits stage) const = 0; 2782 virtual std::string genNoAccessSource (void) const = 0; 2783 2784 std::string genVertexSource (void) const; 2785 std::string genTessCtrlSource (void) const; 2786 std::string genTessEvalSource (void) const; 2787 std::string genGeometrySource (void) const; 2788 std::string genFragmentSource (void) const; 2789 std::string genComputeSource (void) const; 2790 2791 void initPrograms (vk::SourceCollections& programCollection) const; 2792 2793 protected: 2794 const glu::GLSLVersion m_glslVersion; 2795 const vk::VkShaderStageFlags m_exitingStages; 2796 const vk::VkShaderStageFlags m_activeStages; 2797 }; 2798 2799 QuadrantRendederCase::QuadrantRendederCase (tcu::TestContext& testCtx, 2800 const char* name, 2801 const char* description, 2802 glu::GLSLVersion glslVersion, 2803 vk::VkShaderStageFlags exitingStages, 2804 vk::VkShaderStageFlags activeStages) 2805 : vkt::TestCase (testCtx, name, description) 2806 , m_glslVersion (glslVersion) 2807 , m_exitingStages (exitingStages) 2808 , m_activeStages (activeStages) 2809 { 2810 DE_ASSERT((m_exitingStages & m_activeStages) == m_activeStages); 2811 } 2812 2813 std::string QuadrantRendederCase::genVertexSource (void) const 2814 { 2815 const char* const nextStageName = ((m_exitingStages & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0u) ? ("tsc") 2816 : ((m_exitingStages & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0u) ? ("geo") 2817 : ((m_exitingStages & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0u) ? ("frag") 2818 : (DE_NULL); 2819 const char* const fragColorPrec = ((m_exitingStages & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0) ? "highp" : "mediump"; 2820 const char* const versionDecl = glu::getGLSLVersionDeclaration(m_glslVersion); 2821 std::ostringstream buf; 2822 2823 if ((m_activeStages & vk::VK_SHADER_STAGE_VERTEX_BIT) != 0u) 2824 { 2825 const bool onlyVS = (m_activeStages == vk::VK_SHADER_STAGE_VERTEX_BIT); 2826 2827 // active vertex shader 2828 buf << versionDecl << "\n" 2829 << genExtensionDeclarations(vk::VK_SHADER_STAGE_VERTEX_BIT) 2830 << genResourceDeclarations(vk::VK_SHADER_STAGE_VERTEX_BIT, 0) 2831 << "layout(location = 0) out " << fragColorPrec << " vec4 " << nextStageName << "_color;\n" 2832 << (onlyVS ? "" : "layout(location = 1) flat out highp int " + de::toString(nextStageName) + "_quadrant_id;\n") 2833 << genPerVertexBlock(vk::VK_SHADER_STAGE_VERTEX_BIT, m_glslVersion) 2834 << "void main (void)\n" 2835 << "{\n" 2836 << " highp vec4 result_position;\n" 2837 << " highp int quadrant_id;\n" 2838 << s_quadrantGenVertexPosSource 2839 << " gl_Position = result_position;\n" 2840 << (onlyVS ? "" : "\t" + de::toString(nextStageName) + "_quadrant_id = quadrant_id;\n") 2841 << "\n" 2842 << " highp vec4 result_color;\n" 2843 << genResourceAccessSource(vk::VK_SHADER_STAGE_VERTEX_BIT) 2844 << " " << nextStageName << "_color = result_color;\n" 2845 << "}\n"; 2846 } 2847 else 2848 { 2849 // do nothing 2850 buf << versionDecl << "\n" 2851 << genExtensionDeclarations(vk::VK_SHADER_STAGE_VERTEX_BIT) 2852 << "layout(location = 1) flat out highp int " << nextStageName << "_quadrant_id;\n" 2853 << genPerVertexBlock(vk::VK_SHADER_STAGE_VERTEX_BIT, m_glslVersion) 2854 << "void main (void)\n" 2855 << "{\n" 2856 << " highp vec4 result_position;\n" 2857 << " highp int quadrant_id;\n" 2858 << s_quadrantGenVertexPosSource 2859 << " gl_Position = result_position;\n" 2860 << " " << nextStageName << "_quadrant_id = quadrant_id;\n" 2861 << "}\n"; 2862 } 2863 2864 return buf.str(); 2865 } 2866 2867 std::string QuadrantRendederCase::genTessCtrlSource (void) const 2868 { 2869 const char* const versionDecl = glu::getGLSLVersionDeclaration(m_glslVersion); 2870 const bool extRequired = glu::glslVersionIsES(m_glslVersion) && m_glslVersion <= glu::GLSL_VERSION_310_ES; 2871 const char* const tessExtDecl = extRequired ? "#extension GL_EXT_tessellation_shader : require\n" : ""; 2872 std::ostringstream buf; 2873 2874 if ((m_activeStages & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0u) 2875 { 2876 // contributing not implemented 2877 DE_ASSERT(m_activeStages == vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT); 2878 2879 // active tc shader 2880 buf << versionDecl << "\n" 2881 << tessExtDecl 2882 << genExtensionDeclarations(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) 2883 << "layout(vertices=3) out;\n" 2884 << genResourceDeclarations(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, 0) 2885 << "layout(location = 1) flat in highp int tsc_quadrant_id[];\n" 2886 << "layout(location = 0) out highp vec4 tes_color[];\n" 2887 << genPerVertexBlock(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, m_glslVersion) 2888 << "void main (void)\n" 2889 << "{\n" 2890 << " highp vec4 result_color;\n" 2891 << " highp int quadrant_id = tsc_quadrant_id[gl_InvocationID];\n" 2892 << genResourceAccessSource(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) 2893 << "\n" 2894 << " tes_color[gl_InvocationID] = result_color;\n" 2895 << "\n" 2896 << " // no dynamic input block indexing\n" 2897 << " highp vec4 position;\n" 2898 << " if (gl_InvocationID == 0)\n" 2899 << " position = gl_in[0].gl_Position;\n" 2900 << " else if (gl_InvocationID == 1)\n" 2901 << " position = gl_in[1].gl_Position;\n" 2902 << " else\n" 2903 << " position = gl_in[2].gl_Position;\n" 2904 << " gl_out[gl_InvocationID].gl_Position = position;\n" 2905 << " gl_TessLevelInner[0] = 2.8;\n" 2906 << " gl_TessLevelInner[1] = 2.8;\n" 2907 << " gl_TessLevelOuter[0] = 2.8;\n" 2908 << " gl_TessLevelOuter[1] = 2.8;\n" 2909 << " gl_TessLevelOuter[2] = 2.8;\n" 2910 << " gl_TessLevelOuter[3] = 2.8;\n" 2911 << "}\n"; 2912 } 2913 else if ((m_activeStages & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0u) 2914 { 2915 // active te shader, tc passthru 2916 buf << versionDecl << "\n" 2917 << tessExtDecl 2918 << "layout(vertices=3) out;\n" 2919 << "layout(location = 1) flat in highp int tsc_quadrant_id[];\n" 2920 << "layout(location = 1) flat out highp int tes_quadrant_id[];\n" 2921 << genPerVertexBlock(vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, m_glslVersion) 2922 << "void main (void)\n" 2923 << "{\n" 2924 << " tes_quadrant_id[gl_InvocationID] = tsc_quadrant_id[0];\n" 2925 << "\n" 2926 << " // no dynamic input block indexing\n" 2927 << " highp vec4 position;\n" 2928 << " if (gl_InvocationID == 0)\n" 2929 << " position = gl_in[0].gl_Position;\n" 2930 << " else if (gl_InvocationID == 1)\n" 2931 << " position = gl_in[1].gl_Position;\n" 2932 << " else\n" 2933 << " position = gl_in[2].gl_Position;\n" 2934 << " gl_out[gl_InvocationID].gl_Position = position;\n" 2935 << " gl_TessLevelInner[0] = 2.8;\n" 2936 << " gl_TessLevelInner[1] = 2.8;\n" 2937 << " gl_TessLevelOuter[0] = 2.8;\n" 2938 << " gl_TessLevelOuter[1] = 2.8;\n" 2939 << " gl_TessLevelOuter[2] = 2.8;\n" 2940 << " gl_TessLevelOuter[3] = 2.8;\n" 2941 << "}\n"; 2942 } 2943 else 2944 { 2945 // passthrough not implemented 2946 DE_FATAL("not implemented"); 2947 } 2948 2949 return buf.str(); 2950 } 2951 2952 std::string QuadrantRendederCase::genTessEvalSource (void) const 2953 { 2954 const char* const versionDecl = glu::getGLSLVersionDeclaration(m_glslVersion); 2955 const bool extRequired = glu::glslVersionIsES(m_glslVersion) && m_glslVersion <= glu::GLSL_VERSION_310_ES; 2956 const char* const tessExtDecl = extRequired ? "#extension GL_EXT_tessellation_shader : require\n" : ""; 2957 std::ostringstream buf; 2958 2959 if ((m_activeStages & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0u) 2960 { 2961 // contributing not implemented 2962 DE_ASSERT(m_activeStages == vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT); 2963 2964 // active te shader 2965 buf << versionDecl << "\n" 2966 << tessExtDecl 2967 << genExtensionDeclarations(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) 2968 << "layout(triangles) in;\n" 2969 << genResourceDeclarations(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, 0) 2970 << "layout(location = 1) flat in highp int tes_quadrant_id[];\n" 2971 << "layout(location = 0) out mediump vec4 frag_color;\n" 2972 << genPerVertexBlock(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, m_glslVersion) 2973 << "void main (void)\n" 2974 << "{\n" 2975 << " highp vec4 result_color;\n" 2976 << " highp int quadrant_id = tes_quadrant_id[0];\n" 2977 << genResourceAccessSource(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) 2978 << "\n" 2979 << " frag_color = result_color;\n" 2980 << " gl_Position = gl_TessCoord.x * gl_in[0].gl_Position + gl_TessCoord.y * gl_in[1].gl_Position + gl_TessCoord.z * gl_in[2].gl_Position;\n" 2981 << "}\n"; 2982 } 2983 else if ((m_activeStages & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0u) 2984 { 2985 // contributing not implemented 2986 DE_ASSERT(m_activeStages == vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT); 2987 2988 // active tc shader, te is passthru 2989 buf << versionDecl << "\n" 2990 << tessExtDecl 2991 << "layout(triangles) in;\n" 2992 << "layout(location = 0) in highp vec4 tes_color[];\n" 2993 << "layout(location = 0) out mediump vec4 frag_color;\n" 2994 << genPerVertexBlock(vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, m_glslVersion) 2995 << "void main (void)\n" 2996 << "{\n" 2997 << " frag_color = tes_color[0];\n" 2998 << " gl_Position = gl_TessCoord.x * gl_in[0].gl_Position + gl_TessCoord.y * gl_in[1].gl_Position + gl_TessCoord.z * gl_in[2].gl_Position;\n" 2999 << "}\n"; 3000 } 3001 else 3002 { 3003 // passthrough not implemented 3004 DE_FATAL("not implemented"); 3005 } 3006 3007 return buf.str(); 3008 } 3009 3010 std::string QuadrantRendederCase::genGeometrySource (void) const 3011 { 3012 const char* const versionDecl = glu::getGLSLVersionDeclaration(m_glslVersion); 3013 const bool extRequired = glu::glslVersionIsES(m_glslVersion) && m_glslVersion <= glu::GLSL_VERSION_310_ES; 3014 const char* const geomExtDecl = extRequired ? "#extension GL_EXT_geometry_shader : require\n" : ""; 3015 std::ostringstream buf; 3016 3017 if ((m_activeStages & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0u) 3018 { 3019 // contributing not implemented 3020 DE_ASSERT(m_activeStages == vk::VK_SHADER_STAGE_GEOMETRY_BIT); 3021 3022 // active geometry shader 3023 buf << versionDecl << "\n" 3024 << geomExtDecl 3025 << genExtensionDeclarations(vk::VK_SHADER_STAGE_GEOMETRY_BIT) 3026 << "layout(triangles) in;\n" 3027 << "layout(triangle_strip, max_vertices=4) out;\n" 3028 << genResourceDeclarations(vk::VK_SHADER_STAGE_GEOMETRY_BIT, 0) 3029 << "layout(location = 1) flat in highp int geo_quadrant_id[];\n" 3030 << "layout(location = 0) out mediump vec4 frag_color;\n" 3031 << genPerVertexBlock(vk::VK_SHADER_STAGE_GEOMETRY_BIT, m_glslVersion) 3032 << "void main (void)\n" 3033 << "{\n" 3034 << " highp int quadrant_id;\n" 3035 << " highp vec4 result_color;\n" 3036 << "\n" 3037 << " quadrant_id = geo_quadrant_id[0];\n" 3038 << genResourceAccessSource(vk::VK_SHADER_STAGE_GEOMETRY_BIT) 3039 << " frag_color = result_color;\n" 3040 << " gl_Position = gl_in[0].gl_Position;\n" 3041 << " EmitVertex();\n" 3042 << "\n" 3043 << " quadrant_id = geo_quadrant_id[1];\n" 3044 << genResourceAccessSource(vk::VK_SHADER_STAGE_GEOMETRY_BIT) 3045 << " frag_color = result_color;\n" 3046 << " gl_Position = gl_in[1].gl_Position;\n" 3047 << " EmitVertex();\n" 3048 << "\n" 3049 << " quadrant_id = geo_quadrant_id[2];\n" 3050 << genResourceAccessSource(vk::VK_SHADER_STAGE_GEOMETRY_BIT) 3051 << " frag_color = result_color;\n" 3052 << " gl_Position = gl_in[0].gl_Position * 0.5 + gl_in[2].gl_Position * 0.5;\n" 3053 << " EmitVertex();\n" 3054 << "\n" 3055 << " quadrant_id = geo_quadrant_id[0];\n" 3056 << genResourceAccessSource(vk::VK_SHADER_STAGE_GEOMETRY_BIT) 3057 << " frag_color = result_color;\n" 3058 << " gl_Position = gl_in[2].gl_Position;\n" 3059 << " EmitVertex();\n" 3060 << "}\n"; 3061 } 3062 else 3063 { 3064 // passthrough not implemented 3065 DE_FATAL("not implemented"); 3066 } 3067 3068 return buf.str(); 3069 } 3070 3071 std::string QuadrantRendederCase::genFragmentSource (void) const 3072 { 3073 const char* const versionDecl = glu::getGLSLVersionDeclaration(m_glslVersion); 3074 std::ostringstream buf; 3075 3076 if ((m_activeStages & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0u) 3077 { 3078 buf << versionDecl << "\n" 3079 << genExtensionDeclarations(vk::VK_SHADER_STAGE_GEOMETRY_BIT) 3080 << genResourceDeclarations(vk::VK_SHADER_STAGE_FRAGMENT_BIT, 0); 3081 3082 if (m_activeStages != vk::VK_SHADER_STAGE_FRAGMENT_BIT) 3083 { 3084 // there are other stages, this is just a contributor 3085 buf << "layout(location = 0) in mediump vec4 frag_color;\n"; 3086 } 3087 3088 buf << "layout(location = 1) flat in highp int frag_quadrant_id;\n" 3089 << "layout(location = 0) out mediump vec4 o_color;\n" 3090 << "void main (void)\n" 3091 << "{\n" 3092 << " highp int quadrant_id = frag_quadrant_id;\n" 3093 << " highp vec4 result_color;\n" 3094 << genResourceAccessSource(vk::VK_SHADER_STAGE_FRAGMENT_BIT); 3095 3096 if (m_activeStages != vk::VK_SHADER_STAGE_FRAGMENT_BIT) 3097 { 3098 // just contributor 3099 buf << " if (frag_quadrant_id < 2)\n" 3100 << " o_color = result_color;\n" 3101 << " else\n" 3102 << " o_color = frag_color;\n"; 3103 } 3104 else 3105 buf << " o_color = result_color;\n"; 3106 3107 buf << "}\n"; 3108 } 3109 else if (m_activeStages == 0u) 3110 { 3111 // special case, no active stages 3112 buf << versionDecl << "\n" 3113 << "layout(location = 1) flat in highp int frag_quadrant_id;\n" 3114 << "layout(location = 0) out mediump vec4 o_color;\n" 3115 << "void main (void)\n" 3116 << "{\n" 3117 << " highp int quadrant_id = frag_quadrant_id;\n" 3118 << " highp vec4 result_color;\n" 3119 << genNoAccessSource() 3120 << " o_color = result_color;\n" 3121 << "}\n"; 3122 } 3123 else 3124 { 3125 // passthrough 3126 buf << versionDecl << "\n" 3127 << "layout(location = 0) in mediump vec4 frag_color;\n" 3128 "layout(location = 0) out mediump vec4 o_color;\n" 3129 "void main (void)\n" 3130 "{\n" 3131 " o_color = frag_color;\n" 3132 "}\n"; 3133 } 3134 3135 return buf.str(); 3136 } 3137 3138 std::string QuadrantRendederCase::genComputeSource (void) const 3139 { 3140 const char* const versionDecl = glu::getGLSLVersionDeclaration(m_glslVersion); 3141 std::ostringstream buf; 3142 3143 buf << versionDecl << "\n" 3144 << genExtensionDeclarations(vk::VK_SHADER_STAGE_COMPUTE_BIT) 3145 << "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" 3146 << genResourceDeclarations(vk::VK_SHADER_STAGE_COMPUTE_BIT, 1) 3147 << "layout(set = 0, binding = 0, std140) writeonly buffer OutBuf\n" 3148 << "{\n" 3149 << " highp vec4 read_colors[4];\n" 3150 << "} b_out;\n" 3151 << "void main (void)\n" 3152 << "{\n" 3153 << " highp int quadrant_id = int(gl_WorkGroupID.x);\n" 3154 << " highp vec4 result_color;\n" 3155 << genResourceAccessSource(vk::VK_SHADER_STAGE_COMPUTE_BIT) 3156 << " b_out.read_colors[gl_WorkGroupID.x] = result_color;\n" 3157 << "}\n"; 3158 3159 return buf.str(); 3160 } 3161 3162 void QuadrantRendederCase::initPrograms (vk::SourceCollections& programCollection) const 3163 { 3164 if ((m_exitingStages & vk::VK_SHADER_STAGE_VERTEX_BIT) != 0u) 3165 programCollection.glslSources.add("vertex") << glu::VertexSource(genVertexSource()); 3166 3167 if ((m_exitingStages & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0u) 3168 programCollection.glslSources.add("tess_ctrl") << glu::TessellationControlSource(genTessCtrlSource()); 3169 3170 if ((m_exitingStages & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0u) 3171 programCollection.glslSources.add("tess_eval") << glu::TessellationEvaluationSource(genTessEvalSource()); 3172 3173 if ((m_exitingStages & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0u) 3174 programCollection.glslSources.add("geometry") << glu::GeometrySource(genGeometrySource()); 3175 3176 if ((m_exitingStages & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0u) 3177 programCollection.glslSources.add("fragment") << glu::FragmentSource(genFragmentSource()); 3178 3179 if ((m_exitingStages & vk::VK_SHADER_STAGE_COMPUTE_BIT) != 0u) 3180 programCollection.glslSources.add("compute") << glu::ComputeSource(genComputeSource()); 3181 } 3182 3183 class BufferDescriptorCase : public QuadrantRendederCase 3184 { 3185 public: 3186 enum 3187 { 3188 FLAG_VIEW_OFFSET = (1u << 1u), 3189 FLAG_DYNAMIC_OFFSET_ZERO = (1u << 2u), 3190 FLAG_DYNAMIC_OFFSET_NONZERO = (1u << 3u), 3191 }; 3192 // enum continues where resource flags ends 3193 DE_STATIC_ASSERT((deUint32)FLAG_VIEW_OFFSET == (deUint32)RESOURCE_FLAG_LAST); 3194 3195 BufferDescriptorCase (tcu::TestContext& testCtx, 3196 DescriptorUpdateMethod updateMethod, 3197 const char* name, 3198 const char* description, 3199 bool isPrimaryCmdBuf, 3200 vk::VkDescriptorType descriptorType, 3201 vk::VkShaderStageFlags exitingStages, 3202 vk::VkShaderStageFlags activeStages, 3203 ShaderInputInterface shaderInterface, 3204 deUint32 flags); 3205 3206 private: 3207 std::string genExtensionDeclarations (vk::VkShaderStageFlagBits stage) const; 3208 std::string genResourceDeclarations (vk::VkShaderStageFlagBits stage, int numUsedBindings) const; 3209 std::string genResourceAccessSource (vk::VkShaderStageFlagBits stage) const; 3210 std::string genNoAccessSource (void) const; 3211 3212 vkt::TestInstance* createInstance (vkt::Context& context) const; 3213 3214 const DescriptorUpdateMethod m_updateMethod; 3215 const bool m_viewOffset; 3216 const bool m_dynamicOffsetSet; 3217 const bool m_dynamicOffsetNonZero; 3218 const bool m_isPrimaryCmdBuf; 3219 const vk::VkDescriptorType m_descriptorType; 3220 const ShaderInputInterface m_shaderInterface; 3221 }; 3222 3223 BufferDescriptorCase::BufferDescriptorCase (tcu::TestContext& testCtx, 3224 DescriptorUpdateMethod updateMethod, 3225 const char* name, 3226 const char* description, 3227 bool isPrimaryCmdBuf, 3228 vk::VkDescriptorType descriptorType, 3229 vk::VkShaderStageFlags exitingStages, 3230 vk::VkShaderStageFlags activeStages, 3231 ShaderInputInterface shaderInterface, 3232 deUint32 flags) 3233 : QuadrantRendederCase (testCtx, name, description, glu::GLSL_VERSION_310_ES, exitingStages, activeStages) 3234 , m_updateMethod (updateMethod) 3235 , m_viewOffset ((flags & FLAG_VIEW_OFFSET) != 0u) 3236 , m_dynamicOffsetSet ((flags & (FLAG_DYNAMIC_OFFSET_ZERO | FLAG_DYNAMIC_OFFSET_NONZERO)) != 0u) 3237 , m_dynamicOffsetNonZero ((flags & FLAG_DYNAMIC_OFFSET_NONZERO) != 0u) 3238 , m_isPrimaryCmdBuf (isPrimaryCmdBuf) 3239 , m_descriptorType (descriptorType) 3240 , m_shaderInterface (shaderInterface) 3241 { 3242 } 3243 3244 std::string BufferDescriptorCase::genExtensionDeclarations (vk::VkShaderStageFlagBits stage) const 3245 { 3246 DE_UNREF(stage); 3247 return ""; 3248 } 3249 3250 std::string BufferDescriptorCase::genResourceDeclarations (vk::VkShaderStageFlagBits stage, int numUsedBindings) const 3251 { 3252 DE_UNREF(stage); 3253 3254 const bool isUniform = isUniformDescriptorType(m_descriptorType); 3255 const char* const storageType = (isUniform) ? ("uniform") : ("buffer"); 3256 std::ostringstream buf; 3257 3258 switch (m_shaderInterface) 3259 { 3260 case SHADER_INPUT_SINGLE_DESCRIPTOR: 3261 buf << "layout(set = 0, binding = " << (numUsedBindings) << ", std140) " << storageType << " BufferName\n" 3262 << "{\n" 3263 << " highp vec4 colorA;\n" 3264 << " highp vec4 colorB;\n" 3265 << "} b_instance;\n"; 3266 break; 3267 3268 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS: 3269 buf << "layout(set = 0, binding = " << (numUsedBindings) << ", std140) " << storageType << " BufferNameA\n" 3270 << "{\n" 3271 << " highp vec4 colorA;\n" 3272 << " highp vec4 colorB;\n" 3273 << "} b_instanceA;\n" 3274 << "layout(set = 0, binding = " << (numUsedBindings+1) << ", std140) " << storageType << " BufferNameB\n" 3275 << "{\n" 3276 << " highp vec4 colorA;\n" 3277 << " highp vec4 colorB;\n" 3278 << "} b_instanceB;\n"; 3279 break; 3280 3281 case SHADER_INPUT_DESCRIPTOR_ARRAY: 3282 buf << "layout(set = 0, binding = " << (numUsedBindings) << ", std140) " << storageType << " BufferName\n" 3283 << "{\n" 3284 << " highp vec4 colorA;\n" 3285 << " highp vec4 colorB;\n" 3286 << "} b_instances[2];\n"; 3287 break; 3288 3289 default: 3290 DE_FATAL("Impossible"); 3291 } 3292 3293 return buf.str(); 3294 } 3295 3296 std::string BufferDescriptorCase::genResourceAccessSource (vk::VkShaderStageFlagBits stage) const 3297 { 3298 DE_UNREF(stage); 3299 3300 std::ostringstream buf; 3301 3302 switch (m_shaderInterface) 3303 { 3304 case SHADER_INPUT_SINGLE_DESCRIPTOR: 3305 buf << " if (quadrant_id == 1 || quadrant_id == 2)\n" 3306 << " result_color = b_instance.colorA;\n" 3307 << " else\n" 3308 << " result_color = b_instance.colorB;\n"; 3309 break; 3310 3311 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS: 3312 buf << " if (quadrant_id == 1 || quadrant_id == 2)\n" 3313 << " result_color = b_instanceA.colorA;\n" 3314 << " else\n" 3315 << " result_color = b_instanceB.colorB;\n"; 3316 break; 3317 3318 case SHADER_INPUT_DESCRIPTOR_ARRAY: 3319 buf << " if (quadrant_id == 1 || quadrant_id == 2)\n" 3320 << " result_color = b_instances[0].colorA;\n" 3321 << " else\n" 3322 << " result_color = b_instances[1].colorB;\n"; 3323 break; 3324 3325 default: 3326 DE_FATAL("Impossible"); 3327 } 3328 3329 return buf.str(); 3330 } 3331 3332 std::string BufferDescriptorCase::genNoAccessSource (void) const 3333 { 3334 return " if (quadrant_id == 1 || quadrant_id == 2)\n" 3335 " result_color = vec4(0.0, 1.0, 0.0, 1.0);\n" 3336 " else\n" 3337 " result_color = vec4(1.0, 1.0, 0.0, 1.0);\n"; 3338 } 3339 3340 vkt::TestInstance* BufferDescriptorCase::createInstance (vkt::Context& context) const 3341 { 3342 verifyDriverSupport(context.getDeviceFeatures(), context.getDeviceExtensions(), m_updateMethod, m_descriptorType, m_activeStages); 3343 3344 if (m_exitingStages == vk::VK_SHADER_STAGE_COMPUTE_BIT) 3345 { 3346 DE_ASSERT(m_isPrimaryCmdBuf); // secondaries are only valid within renderpass 3347 return new BufferComputeInstance(context, m_updateMethod, m_descriptorType, m_shaderInterface, m_viewOffset, m_dynamicOffsetSet, m_dynamicOffsetNonZero); 3348 } 3349 else 3350 return new BufferRenderInstance(context, m_updateMethod, m_isPrimaryCmdBuf, m_descriptorType, m_activeStages, m_shaderInterface, m_viewOffset, m_dynamicOffsetSet, m_dynamicOffsetNonZero); 3351 } 3352 3353 class ImageInstanceImages 3354 { 3355 public: 3356 ImageInstanceImages (const vk::DeviceInterface& vki, 3357 vk::VkDevice device, 3358 deUint32 queueFamilyIndex, 3359 vk::VkQueue queue, 3360 vk::Allocator& allocator, 3361 vk::VkDescriptorType descriptorType, 3362 vk::VkImageViewType viewType, 3363 int numImages, 3364 deUint32 baseMipLevel, 3365 deUint32 baseArraySlice); 3366 3367 private: 3368 static vk::Move<vk::VkImage> createImage (const vk::DeviceInterface& vki, 3369 vk::VkDevice device, 3370 vk::Allocator& allocator, 3371 vk::VkDescriptorType descriptorType, 3372 vk::VkImageViewType viewType, 3373 const tcu::TextureLevelPyramid& sourceImage, 3374 de::MovePtr<vk::Allocation>* outAllocation); 3375 3376 static vk::Move<vk::VkImageView> createImageView (const vk::DeviceInterface& vki, 3377 vk::VkDevice device, 3378 vk::VkImageViewType viewType, 3379 const tcu::TextureLevelPyramid& sourceImage, 3380 vk::VkImage image, 3381 deUint32 baseMipLevel, 3382 deUint32 baseArraySlice); 3383 3384 void populateSourceImage (tcu::TextureLevelPyramid* dst, 3385 bool isFirst) const; 3386 3387 void uploadImage (const vk::DeviceInterface& vki, 3388 vk::VkDevice device, 3389 deUint32 queueFamilyIndex, 3390 vk::VkQueue queue, 3391 vk::Allocator& allocator, 3392 vk::VkImage image, 3393 vk::VkImageLayout layout, 3394 const tcu::TextureLevelPyramid& data); 3395 3396 protected: 3397 enum 3398 { 3399 IMAGE_SIZE = 64, 3400 NUM_MIP_LEVELS = 2, 3401 ARRAY_SIZE = 2, 3402 }; 3403 3404 const vk::VkImageViewType m_viewType; 3405 const deUint32 m_baseMipLevel; 3406 const deUint32 m_baseArraySlice; 3407 3408 const tcu::TextureFormat m_imageFormat; 3409 tcu::TextureLevelPyramid m_sourceImageA; 3410 tcu::TextureLevelPyramid m_sourceImageB; 3411 3412 de::MovePtr<vk::Allocation> m_imageMemoryA; 3413 de::MovePtr<vk::Allocation> m_imageMemoryB; 3414 vk::Move<vk::VkImage> m_imageA; 3415 vk::Move<vk::VkImage> m_imageB; 3416 vk::Move<vk::VkImageView> m_imageViewA; 3417 vk::Move<vk::VkImageView> m_imageViewB; 3418 }; 3419 3420 ImageInstanceImages::ImageInstanceImages (const vk::DeviceInterface& vki, 3421 vk::VkDevice device, 3422 deUint32 queueFamilyIndex, 3423 vk::VkQueue queue, 3424 vk::Allocator& allocator, 3425 vk::VkDescriptorType descriptorType, 3426 vk::VkImageViewType viewType, 3427 int numImages, 3428 deUint32 baseMipLevel, 3429 deUint32 baseArraySlice) 3430 : m_viewType (viewType) 3431 , m_baseMipLevel (baseMipLevel) 3432 , m_baseArraySlice (baseArraySlice) 3433 , m_imageFormat (tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8) 3434 , m_sourceImageA (m_imageFormat, NUM_MIP_LEVELS) 3435 , m_sourceImageB (m_imageFormat, NUM_MIP_LEVELS) 3436 , m_imageMemoryA (DE_NULL) 3437 , m_imageMemoryB (DE_NULL) 3438 , m_imageA (vk::Move<vk::VkImage>()) 3439 , m_imageB (vk::Move<vk::VkImage>()) 3440 , m_imageViewA (vk::Move<vk::VkImageView>()) 3441 , m_imageViewB (vk::Move<vk::VkImageView>()) 3442 { 3443 const vk::VkImageLayout layout = getImageLayoutForDescriptorType(descriptorType); 3444 3445 DE_ASSERT(numImages == 1 || numImages == 2); 3446 3447 populateSourceImage(&m_sourceImageA, true); 3448 m_imageA = createImage(vki, device, allocator, descriptorType, viewType, m_sourceImageA, &m_imageMemoryA); 3449 m_imageViewA = createImageView(vki, device, viewType, m_sourceImageA, *m_imageA, m_baseMipLevel, m_baseArraySlice); 3450 uploadImage(vki, device, queueFamilyIndex, queue, allocator, *m_imageA, layout, m_sourceImageA); 3451 3452 if (numImages == 2) 3453 { 3454 populateSourceImage(&m_sourceImageB, false); 3455 m_imageB = createImage(vki, device, allocator, descriptorType, viewType, m_sourceImageB, &m_imageMemoryB); 3456 m_imageViewB = createImageView(vki, device, viewType, m_sourceImageB, *m_imageB, m_baseMipLevel, m_baseArraySlice); 3457 uploadImage(vki, device, queueFamilyIndex, queue, allocator, *m_imageB, layout, m_sourceImageB); 3458 } 3459 } 3460 3461 vk::Move<vk::VkImage> ImageInstanceImages::createImage (const vk::DeviceInterface& vki, 3462 vk::VkDevice device, 3463 vk::Allocator& allocator, 3464 vk::VkDescriptorType descriptorType, 3465 vk::VkImageViewType viewType, 3466 const tcu::TextureLevelPyramid& sourceImage, 3467 de::MovePtr<vk::Allocation>* outAllocation) 3468 { 3469 const tcu::ConstPixelBufferAccess baseLevel = sourceImage.getLevel(0); 3470 const bool isCube = (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY); 3471 const bool isStorage = (descriptorType == vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE); 3472 const deUint32 readUsage = (isStorage) ? (vk::VK_IMAGE_USAGE_STORAGE_BIT) : (vk::VK_IMAGE_USAGE_SAMPLED_BIT); 3473 const deUint32 arraySize = (viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ? (baseLevel.getHeight()) 3474 : (viewType == vk::VK_IMAGE_VIEW_TYPE_2D || viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY) ? (baseLevel.getDepth()) 3475 : (viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? (1) 3476 : (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ? (baseLevel.getDepth()) // cube: numFaces * numLayers 3477 : (0); 3478 const vk::VkExtent3D extent = 3479 { 3480 // x 3481 (deUint32)baseLevel.getWidth(), 3482 3483 // y 3484 (viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ? (1u) : (deUint32)baseLevel.getHeight(), 3485 3486 // z 3487 (viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? ((deUint32)baseLevel.getDepth()) : (1u), 3488 }; 3489 const vk::VkImageCreateInfo createInfo = 3490 { 3491 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, 3492 DE_NULL, 3493 isCube ? (vk::VkImageCreateFlags)vk::VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : (vk::VkImageCreateFlags)0, 3494 viewTypeToImageType(viewType), // imageType 3495 vk::mapTextureFormat(baseLevel.getFormat()), // format 3496 extent, // extent 3497 (deUint32)sourceImage.getNumLevels(), // mipLevels 3498 arraySize, // arraySize 3499 vk::VK_SAMPLE_COUNT_1_BIT, // samples 3500 vk::VK_IMAGE_TILING_OPTIMAL, // tiling 3501 readUsage | vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT, // usage 3502 vk::VK_SHARING_MODE_EXCLUSIVE, // sharingMode 3503 0u, // queueFamilyCount 3504 DE_NULL, // pQueueFamilyIndices 3505 vk::VK_IMAGE_LAYOUT_UNDEFINED, // initialLayout 3506 }; 3507 vk::Move<vk::VkImage> image (vk::createImage(vki, device, &createInfo)); 3508 3509 *outAllocation = allocateAndBindObjectMemory(vki, device, allocator, *image, vk::MemoryRequirement::Any); 3510 return image; 3511 } 3512 3513 vk::Move<vk::VkImageView> ImageInstanceImages::createImageView (const vk::DeviceInterface& vki, 3514 vk::VkDevice device, 3515 vk::VkImageViewType viewType, 3516 const tcu::TextureLevelPyramid& sourceImage, 3517 vk::VkImage image, 3518 deUint32 baseMipLevel, 3519 deUint32 baseArraySlice) 3520 { 3521 const tcu::ConstPixelBufferAccess baseLevel = sourceImage.getLevel(0); 3522 const deUint32 viewTypeBaseSlice = (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ? (6 * baseArraySlice) : (baseArraySlice); 3523 const deUint32 viewArraySize = (viewType == vk::VK_IMAGE_VIEW_TYPE_1D) ? (1) 3524 : (viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ? (baseLevel.getHeight() - viewTypeBaseSlice) 3525 : (viewType == vk::VK_IMAGE_VIEW_TYPE_2D) ? (1) 3526 : (viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY) ? (baseLevel.getDepth() - viewTypeBaseSlice) 3527 : (viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? (1) 3528 : (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE) ? (6) 3529 : (viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ? (baseLevel.getDepth() - viewTypeBaseSlice) // cube: numFaces * numLayers 3530 : (0); 3531 3532 DE_ASSERT(viewArraySize > 0); 3533 3534 const vk::VkImageSubresourceRange resourceRange = 3535 { 3536 vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask 3537 baseMipLevel, // baseMipLevel 3538 sourceImage.getNumLevels() - baseMipLevel, // mipLevels 3539 viewTypeBaseSlice, // baseArraySlice 3540 viewArraySize, // arraySize 3541 }; 3542 const vk::VkImageViewCreateInfo createInfo = 3543 { 3544 vk::VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, 3545 DE_NULL, 3546 (vk::VkImageViewCreateFlags)0, 3547 image, // image 3548 viewType, // viewType 3549 vk::mapTextureFormat(baseLevel.getFormat()), // format 3550 { 3551 vk::VK_COMPONENT_SWIZZLE_R, 3552 vk::VK_COMPONENT_SWIZZLE_G, 3553 vk::VK_COMPONENT_SWIZZLE_B, 3554 vk::VK_COMPONENT_SWIZZLE_A 3555 }, // channels 3556 resourceRange, // subresourceRange 3557 }; 3558 return vk::createImageView(vki, device, &createInfo); 3559 } 3560 3561 void ImageInstanceImages::populateSourceImage (tcu::TextureLevelPyramid* dst, bool isFirst) const 3562 { 3563 const int numLevels = dst->getNumLevels(); 3564 3565 for (int level = 0; level < numLevels; ++level) 3566 { 3567 const int width = IMAGE_SIZE >> level; 3568 const int height = (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D || m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ? (ARRAY_SIZE) 3569 : (IMAGE_SIZE >> level); 3570 const int depth = (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D || m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ? (1) 3571 : (m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D || m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY) ? (ARRAY_SIZE) 3572 : (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ? (6 * ARRAY_SIZE) 3573 : (m_viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? (IMAGE_SIZE >> level) 3574 : (1); 3575 3576 dst->allocLevel(level, width, height, depth); 3577 3578 { 3579 const tcu::PixelBufferAccess levelAccess = dst->getLevel(level); 3580 3581 for (int z = 0; z < depth; ++z) 3582 for (int y = 0; y < height; ++y) 3583 for (int x = 0; x < width; ++x) 3584 { 3585 const int gradPos = x + y + z; 3586 const int gradMax = width + height + depth - 3; 3587 3588 const int red = 255 * gradPos / gradMax; //!< gradient from 0 -> max (detects large offset errors) 3589 const int green = ((gradPos % 2 == 0) ? (127) : (0)) + ((gradPos % 4 < 3) ? (128) : (0)); //!< 3-level M pattern (detects small offset errors) 3590 const int blue = (128 * level / numLevels) + (isFirst ? 127 : 0); //!< level and image index (detects incorrect lod / image) 3591 3592 DE_ASSERT(de::inRange(red, 0, 255)); 3593 DE_ASSERT(de::inRange(green, 0, 255)); 3594 DE_ASSERT(de::inRange(blue, 0, 255)); 3595 3596 levelAccess.setPixel(tcu::IVec4(red, green, blue, 255), x, y, z); 3597 } 3598 } 3599 } 3600 } 3601 3602 void ImageInstanceImages::uploadImage (const vk::DeviceInterface& vki, 3603 vk::VkDevice device, 3604 deUint32 queueFamilyIndex, 3605 vk::VkQueue queue, 3606 vk::Allocator& allocator, 3607 vk::VkImage image, 3608 vk::VkImageLayout layout, 3609 const tcu::TextureLevelPyramid& data) 3610 { 3611 const deUint32 arraySize = (m_viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? (1) : 3612 (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ? (6 * (deUint32)ARRAY_SIZE) : 3613 ((deUint32)ARRAY_SIZE); 3614 const deUint32 dataBufferSize = getTextureLevelPyramidDataSize(data); 3615 const vk::VkBufferCreateInfo bufferCreateInfo = 3616 { 3617 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, 3618 DE_NULL, 3619 0u, // flags 3620 dataBufferSize, // size 3621 vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT, // usage 3622 vk::VK_SHARING_MODE_EXCLUSIVE, // sharingMode 3623 0u, // queueFamilyCount 3624 DE_NULL, // pQueueFamilyIndices 3625 }; 3626 const vk::Unique<vk::VkBuffer> dataBuffer (vk::createBuffer(vki, device, &bufferCreateInfo)); 3627 const de::MovePtr<vk::Allocation> dataBufferMemory = allocateAndBindObjectMemory(vki, device, allocator, *dataBuffer, vk::MemoryRequirement::HostVisible); 3628 const vk::VkFenceCreateInfo fenceCreateInfo = 3629 { 3630 vk::VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, 3631 DE_NULL, 3632 0u, // flags 3633 }; 3634 const vk::VkBufferMemoryBarrier preMemoryBarrier = 3635 { 3636 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 3637 DE_NULL, 3638 vk::VK_ACCESS_HOST_WRITE_BIT, // outputMask 3639 vk::VK_ACCESS_TRANSFER_READ_BIT, // inputMask 3640 VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex 3641 VK_QUEUE_FAMILY_IGNORED, // destQueueFamilyIndex 3642 *dataBuffer, // buffer 3643 0u, // offset 3644 dataBufferSize, // size 3645 }; 3646 const vk::VkImageSubresourceRange fullSubrange = 3647 { 3648 vk::VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask 3649 0u, // baseMipLevel 3650 (deUint32)data.getNumLevels(), // mipLevels 3651 0u, // baseArraySlice 3652 arraySize, // arraySize 3653 }; 3654 const vk::VkImageMemoryBarrier preImageBarrier = 3655 { 3656 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 3657 DE_NULL, 3658 0u, // outputMask 3659 vk::VK_ACCESS_TRANSFER_WRITE_BIT, // inputMask 3660 vk::VK_IMAGE_LAYOUT_UNDEFINED, // oldLayout 3661 vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // newLayout 3662 VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex 3663 VK_QUEUE_FAMILY_IGNORED, // destQueueFamilyIndex 3664 image, // image 3665 fullSubrange // subresourceRange 3666 }; 3667 const vk::VkImageMemoryBarrier postImageBarrier = 3668 { 3669 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 3670 DE_NULL, 3671 vk::VK_ACCESS_TRANSFER_WRITE_BIT, // outputMask 3672 vk::VK_ACCESS_SHADER_READ_BIT, // inputMask 3673 vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // oldLayout 3674 layout, // newLayout 3675 VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex 3676 VK_QUEUE_FAMILY_IGNORED, // destQueueFamilyIndex 3677 image, // image 3678 fullSubrange // subresourceRange 3679 }; 3680 const vk::VkCommandPoolCreateInfo cmdPoolCreateInfo = 3681 { 3682 vk::VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, 3683 DE_NULL, 3684 vk::VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, // flags 3685 queueFamilyIndex, // queueFamilyIndex 3686 }; 3687 const vk::Unique<vk::VkCommandPool> cmdPool (vk::createCommandPool(vki, device, &cmdPoolCreateInfo)); 3688 const vk::VkCommandBufferAllocateInfo cmdBufCreateInfo = 3689 { 3690 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, 3691 DE_NULL, 3692 *cmdPool, // cmdPool 3693 vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY, // level 3694 1u, // count 3695 }; 3696 const vk::VkCommandBufferBeginInfo cmdBufBeginInfo = 3697 { 3698 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 3699 DE_NULL, 3700 vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, // flags 3701 (const vk::VkCommandBufferInheritanceInfo*)DE_NULL, 3702 }; 3703 3704 const vk::Unique<vk::VkCommandBuffer> cmd (vk::allocateCommandBuffer(vki, device, &cmdBufCreateInfo)); 3705 const vk::Unique<vk::VkFence> cmdCompleteFence (vk::createFence(vki, device, &fenceCreateInfo)); 3706 const deUint64 infiniteTimeout = ~(deUint64)0u; 3707 std::vector<vk::VkBufferImageCopy> copySlices; 3708 3709 // copy data to buffer 3710 writeTextureLevelPyramidData(dataBufferMemory->getHostPtr(), dataBufferSize, data, m_viewType , ©Slices); 3711 flushMappedMemoryRange(vki, device, dataBufferMemory->getMemory(), dataBufferMemory->getOffset(), dataBufferSize); 3712 3713 // record command buffer 3714 VK_CHECK(vki.beginCommandBuffer(*cmd, &cmdBufBeginInfo)); 3715 vki.cmdPipelineBarrier(*cmd, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0, 3716 0, (const vk::VkMemoryBarrier*)DE_NULL, 3717 1, &preMemoryBarrier, 3718 1, &preImageBarrier); 3719 vki.cmdCopyBufferToImage(*cmd, *dataBuffer, image, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, (deUint32)copySlices.size(), ©Slices[0]); 3720 vki.cmdPipelineBarrier(*cmd, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (vk::VkDependencyFlags)0, 3721 0, (const vk::VkMemoryBarrier*)DE_NULL, 3722 0, (const vk::VkBufferMemoryBarrier*)DE_NULL, 3723 1, &postImageBarrier); 3724 VK_CHECK(vki.endCommandBuffer(*cmd)); 3725 3726 // submit and wait for command buffer to complete before killing it 3727 { 3728 const vk::VkSubmitInfo submitInfo = 3729 { 3730 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO, 3731 DE_NULL, 3732 0u, 3733 (const vk::VkSemaphore*)0, 3734 (const vk::VkPipelineStageFlags*)DE_NULL, 3735 1u, 3736 &cmd.get(), 3737 0u, 3738 (const vk::VkSemaphore*)0, 3739 }; 3740 VK_CHECK(vki.queueSubmit(queue, 1, &submitInfo, *cmdCompleteFence)); 3741 } 3742 VK_CHECK(vki.waitForFences(device, 1, &cmdCompleteFence.get(), 0u, infiniteTimeout)); // \note: timeout is failure 3743 } 3744 3745 class ImageFetchInstanceImages : private ImageInstanceImages 3746 { 3747 public: 3748 ImageFetchInstanceImages (const vk::DeviceInterface& vki, 3749 vk::VkDevice device, 3750 deUint32 queueFamilyIndex, 3751 vk::VkQueue queue, 3752 vk::Allocator& allocator, 3753 vk::VkDescriptorType descriptorType, 3754 ShaderInputInterface shaderInterface, 3755 vk::VkImageViewType viewType, 3756 deUint32 baseMipLevel, 3757 deUint32 baseArraySlice); 3758 3759 static tcu::IVec3 getFetchPos (vk::VkImageViewType viewType, deUint32 baseMipLevel, deUint32 baseArraySlice, int fetchPosNdx); 3760 tcu::Vec4 fetchImageValue (int fetchPosNdx) const; 3761 3762 inline vk::VkImageView getImageViewA (void) const { return *m_imageViewA; } 3763 inline vk::VkImageView getImageViewB (void) const { return *m_imageViewB; } 3764 3765 private: 3766 enum 3767 { 3768 // some arbitrary sample points for all four quadrants 3769 SAMPLE_POINT_0_X = 6, 3770 SAMPLE_POINT_0_Y = 13, 3771 SAMPLE_POINT_0_Z = 49, 3772 3773 SAMPLE_POINT_1_X = 51, 3774 SAMPLE_POINT_1_Y = 40, 3775 SAMPLE_POINT_1_Z = 44, 3776 3777 SAMPLE_POINT_2_X = 42, 3778 SAMPLE_POINT_2_Y = 26, 3779 SAMPLE_POINT_2_Z = 19, 3780 3781 SAMPLE_POINT_3_X = 25, 3782 SAMPLE_POINT_3_Y = 25, 3783 SAMPLE_POINT_3_Z = 18, 3784 }; 3785 3786 const ShaderInputInterface m_shaderInterface; 3787 }; 3788 3789 ImageFetchInstanceImages::ImageFetchInstanceImages (const vk::DeviceInterface& vki, 3790 vk::VkDevice device, 3791 deUint32 queueFamilyIndex, 3792 vk::VkQueue queue, 3793 vk::Allocator& allocator, 3794 vk::VkDescriptorType descriptorType, 3795 ShaderInputInterface shaderInterface, 3796 vk::VkImageViewType viewType, 3797 deUint32 baseMipLevel, 3798 deUint32 baseArraySlice) 3799 : ImageInstanceImages (vki, 3800 device, 3801 queueFamilyIndex, 3802 queue, 3803 allocator, 3804 descriptorType, 3805 viewType, 3806 getInterfaceNumResources(shaderInterface), // numImages 3807 baseMipLevel, 3808 baseArraySlice) 3809 , m_shaderInterface (shaderInterface) 3810 { 3811 } 3812 3813 bool isImageViewTypeArray (vk::VkImageViewType type) 3814 { 3815 return type == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY || type == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY || type == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY; 3816 } 3817 3818 tcu::IVec3 ImageFetchInstanceImages::getFetchPos (vk::VkImageViewType viewType, deUint32 baseMipLevel, deUint32 baseArraySlice, int fetchPosNdx) 3819 { 3820 const tcu::IVec3 fetchPositions[4] = 3821 { 3822 tcu::IVec3(SAMPLE_POINT_0_X, SAMPLE_POINT_0_Y, SAMPLE_POINT_0_Z), 3823 tcu::IVec3(SAMPLE_POINT_1_X, SAMPLE_POINT_1_Y, SAMPLE_POINT_1_Z), 3824 tcu::IVec3(SAMPLE_POINT_2_X, SAMPLE_POINT_2_Y, SAMPLE_POINT_2_Z), 3825 tcu::IVec3(SAMPLE_POINT_3_X, SAMPLE_POINT_3_Y, SAMPLE_POINT_3_Z), 3826 }; 3827 const tcu::IVec3 coord = de::getSizedArrayElement<4>(fetchPositions, fetchPosNdx); 3828 const deUint32 imageSize = (deUint32)IMAGE_SIZE >> baseMipLevel; 3829 const deUint32 arraySize = isImageViewTypeArray(viewType) ? ARRAY_SIZE - baseArraySlice : 1; 3830 3831 switch (viewType) 3832 { 3833 case vk::VK_IMAGE_VIEW_TYPE_1D: 3834 case vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY: return tcu::IVec3(coord.x() % imageSize, coord.y() % arraySize, 0); 3835 case vk::VK_IMAGE_VIEW_TYPE_2D: 3836 case vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY: return tcu::IVec3(coord.x() % imageSize, coord.y() % imageSize, coord.z() % arraySize); 3837 case vk::VK_IMAGE_VIEW_TYPE_CUBE: 3838 case vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY: return tcu::IVec3(coord.x() % imageSize, coord.y() % imageSize, coord.z() % (arraySize * 6)); 3839 case vk::VK_IMAGE_VIEW_TYPE_3D: return tcu::IVec3(coord.x() % imageSize, coord.y() % imageSize, coord.z() % imageSize); 3840 default: 3841 DE_FATAL("Impossible"); 3842 return tcu::IVec3(); 3843 } 3844 } 3845 3846 tcu::Vec4 ImageFetchInstanceImages::fetchImageValue (int fetchPosNdx) const 3847 { 3848 DE_ASSERT(de::inBounds(fetchPosNdx, 0, 4)); 3849 3850 const tcu::TextureLevelPyramid& fetchSrcA = m_sourceImageA; 3851 const tcu::TextureLevelPyramid& fetchSrcB = (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? (m_sourceImageA) : (m_sourceImageB); 3852 const tcu::TextureLevelPyramid& fetchSrc = ((fetchPosNdx % 2) == 0) ? (fetchSrcA) : (fetchSrcB); // sampling order is ABAB 3853 tcu::IVec3 fetchPos = getFetchPos(m_viewType, m_baseMipLevel, m_baseArraySlice, fetchPosNdx); 3854 3855 // add base array layer into the appropriate coordinate, based on the view type 3856 if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) 3857 fetchPos.z() += 6 * m_baseArraySlice; 3858 else if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D || m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) 3859 fetchPos.y() += m_baseArraySlice; 3860 else 3861 fetchPos.z() += m_baseArraySlice; 3862 3863 return fetchSrc.getLevel(m_baseMipLevel).getPixel(fetchPos.x(), fetchPos.y(), fetchPos.z()); 3864 } 3865 3866 class ImageFetchRenderInstance : public SingleCmdRenderInstance 3867 { 3868 public: 3869 ImageFetchRenderInstance (vkt::Context& context, 3870 DescriptorUpdateMethod updateMethod, 3871 bool isPrimaryCmdBuf, 3872 vk::VkDescriptorType descriptorType, 3873 vk::VkShaderStageFlags stageFlags, 3874 ShaderInputInterface shaderInterface, 3875 vk::VkImageViewType viewType, 3876 deUint32 baseMipLevel, 3877 deUint32 baseArraySlice); 3878 3879 private: 3880 static vk::Move<vk::VkDescriptorSetLayout> createDescriptorSetLayout (const vk::DeviceInterface& vki, 3881 vk::VkDevice device, 3882 vk::VkDescriptorType descriptorType, 3883 ShaderInputInterface shaderInterface, 3884 vk::VkShaderStageFlags stageFlags, 3885 DescriptorUpdateMethod updateMethod); 3886 3887 static vk::Move<vk::VkPipelineLayout> createPipelineLayout (const vk::DeviceInterface& vki, 3888 vk::VkDevice device, 3889 vk::VkDescriptorSetLayout descriptorSetLayout); 3890 3891 static vk::Move<vk::VkDescriptorPool> createDescriptorPool (const vk::DeviceInterface& vki, 3892 vk::VkDevice device, 3893 vk::VkDescriptorType descriptorType, 3894 ShaderInputInterface shaderInterface); 3895 3896 static vk::Move<vk::VkDescriptorSet> createDescriptorSet (const vk::DeviceInterface& vki, 3897 DescriptorUpdateMethod updateMethod, 3898 vk::VkDevice device, 3899 vk::VkDescriptorType descriptorType, 3900 ShaderInputInterface shaderInterface, 3901 vk::VkDescriptorSetLayout layout, 3902 vk::VkDescriptorPool pool, 3903 vk::VkImageView viewA, 3904 vk::VkImageView viewB, 3905 vk::DescriptorSetUpdateBuilder& updateBuilder, 3906 vk::Move<vk::VkDescriptorUpdateTemplateKHR>& updateTemplate, 3907 RawUpdateRegistry& updateRegistry, 3908 vk::VkPipelineLayout pipelineLayout = DE_NULL); 3909 3910 static void writeDescriptorSet (const vk::DeviceInterface& vki, 3911 vk::VkDevice device, 3912 vk::VkDescriptorType descriptorType, 3913 ShaderInputInterface shaderInterface, 3914 vk::VkDescriptorSetLayout layout, 3915 vk::VkDescriptorPool pool, 3916 vk::VkImageView viewA, 3917 vk::VkImageView viewB, 3918 vk::VkDescriptorSet descriptorSet, 3919 vk::DescriptorSetUpdateBuilder& updateBuilder, 3920 DescriptorUpdateMethod updateMethod = DESCRIPTOR_UPDATE_METHOD_NORMAL); 3921 3922 static void writeDescriptorSetWithTemplate (const vk::DeviceInterface& vki, 3923 vk::VkDevice device, 3924 vk::VkDescriptorType descriptorType, 3925 ShaderInputInterface shaderInterface, 3926 vk::VkDescriptorSetLayout layout, 3927 vk::VkDescriptorPool pool, 3928 vk::VkImageView viewA, 3929 vk::VkImageView viewB, 3930 vk::VkDescriptorSet descriptorSet, 3931 vk::Move<vk::VkDescriptorUpdateTemplateKHR>& updateTemplate, 3932 RawUpdateRegistry& updateRegistry, 3933 bool withPush = false, 3934 vk::VkPipelineLayout pipelineLayout = 0); 3935 3936 void logTestPlan (void) const; 3937 vk::VkPipelineLayout getPipelineLayout (void) const; 3938 void writeDrawCmdBuffer (vk::VkCommandBuffer cmd) const; 3939 tcu::TestStatus verifyResultImage (const tcu::ConstPixelBufferAccess& result) const; 3940 3941 enum 3942 { 3943 RENDER_SIZE = 128, 3944 }; 3945 3946 const DescriptorUpdateMethod m_updateMethod; 3947 const vk::VkDescriptorType m_descriptorType; 3948 const vk::VkShaderStageFlags m_stageFlags; 3949 const ShaderInputInterface m_shaderInterface; 3950 const vk::VkImageViewType m_viewType; 3951 const deUint32 m_baseMipLevel; 3952 const deUint32 m_baseArraySlice; 3953 3954 vk::Move<vk::VkDescriptorUpdateTemplateKHR> m_updateTemplate; 3955 RawUpdateRegistry m_updateRegistry; 3956 vk::DescriptorSetUpdateBuilder m_updateBuilder; 3957 const vk::Unique<vk::VkDescriptorSetLayout> m_descriptorSetLayout; 3958 const vk::Unique<vk::VkPipelineLayout> m_pipelineLayout; 3959 const ImageFetchInstanceImages m_images; 3960 const vk::Unique<vk::VkDescriptorPool> m_descriptorPool; 3961 const vk::Unique<vk::VkDescriptorSet> m_descriptorSet; 3962 }; 3963 3964 ImageFetchRenderInstance::ImageFetchRenderInstance (vkt::Context& context, 3965 DescriptorUpdateMethod updateMethod, 3966 bool isPrimaryCmdBuf, 3967 vk::VkDescriptorType descriptorType, 3968 vk::VkShaderStageFlags stageFlags, 3969 ShaderInputInterface shaderInterface, 3970 vk::VkImageViewType viewType, 3971 deUint32 baseMipLevel, 3972 deUint32 baseArraySlice) 3973 : SingleCmdRenderInstance (context, isPrimaryCmdBuf, tcu::UVec2(RENDER_SIZE, RENDER_SIZE)) 3974 , m_updateMethod (updateMethod) 3975 , m_descriptorType (descriptorType) 3976 , m_stageFlags (stageFlags) 3977 , m_shaderInterface (shaderInterface) 3978 , m_viewType (viewType) 3979 , m_baseMipLevel (baseMipLevel) 3980 , m_baseArraySlice (baseArraySlice) 3981 , m_updateTemplate () 3982 , m_updateRegistry () 3983 , m_updateBuilder () 3984 , m_descriptorSetLayout (createDescriptorSetLayout(m_vki, m_device, m_descriptorType, m_shaderInterface, m_stageFlags, m_updateMethod)) 3985 , m_pipelineLayout (createPipelineLayout(m_vki, m_device, *m_descriptorSetLayout)) 3986 , m_images (m_vki, m_device, m_queueFamilyIndex, m_queue, m_allocator, m_descriptorType, m_shaderInterface, m_viewType, m_baseMipLevel, m_baseArraySlice) 3987 , m_descriptorPool (createDescriptorPool(m_vki, m_device, m_descriptorType, m_shaderInterface)) 3988 , m_descriptorSet (createDescriptorSet(m_vki, m_updateMethod, m_device, m_descriptorType, m_shaderInterface, *m_descriptorSetLayout, *m_descriptorPool, m_images.getImageViewA(), m_images.getImageViewB(), m_updateBuilder, m_updateTemplate, m_updateRegistry, *m_pipelineLayout)) 3989 { 3990 } 3991 3992 vk::Move<vk::VkDescriptorSetLayout> ImageFetchRenderInstance::createDescriptorSetLayout (const vk::DeviceInterface& vki, 3993 vk::VkDevice device, 3994 vk::VkDescriptorType descriptorType, 3995 ShaderInputInterface shaderInterface, 3996 vk::VkShaderStageFlags stageFlags, 3997 DescriptorUpdateMethod updateMethod) 3998 { 3999 vk::DescriptorSetLayoutBuilder builder; 4000 vk::VkDescriptorSetLayoutCreateFlags extraFlags = 0; 4001 4002 if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE || 4003 updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH) 4004 { 4005 extraFlags |= vk::VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR; 4006 } 4007 4008 switch (shaderInterface) 4009 { 4010 case SHADER_INPUT_SINGLE_DESCRIPTOR: 4011 builder.addSingleBinding(descriptorType, stageFlags); 4012 break; 4013 4014 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS: 4015 builder.addSingleBinding(descriptorType, stageFlags); 4016 builder.addSingleBinding(descriptorType, stageFlags); 4017 break; 4018 4019 case SHADER_INPUT_DESCRIPTOR_ARRAY: 4020 builder.addArrayBinding(descriptorType, 2u, stageFlags); 4021 break; 4022 4023 default: 4024 DE_FATAL("Impossible"); 4025 } 4026 4027 return builder.build(vki, device, extraFlags); 4028 } 4029 4030 vk::Move<vk::VkPipelineLayout> ImageFetchRenderInstance::createPipelineLayout (const vk::DeviceInterface& vki, 4031 vk::VkDevice device, 4032 vk::VkDescriptorSetLayout descriptorSetLayout) 4033 { 4034 const vk::VkPipelineLayoutCreateInfo createInfo = 4035 { 4036 vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, 4037 DE_NULL, 4038 (vk::VkPipelineLayoutCreateFlags)0, 4039 1, // descriptorSetCount 4040 &descriptorSetLayout, // pSetLayouts 4041 0u, // pushConstantRangeCount 4042 DE_NULL, // pPushConstantRanges 4043 }; 4044 return vk::createPipelineLayout(vki, device, &createInfo); 4045 } 4046 4047 vk::Move<vk::VkDescriptorPool> ImageFetchRenderInstance::createDescriptorPool (const vk::DeviceInterface& vki, 4048 vk::VkDevice device, 4049 vk::VkDescriptorType descriptorType, 4050 ShaderInputInterface shaderInterface) 4051 { 4052 return vk::DescriptorPoolBuilder() 4053 .addType(descriptorType, getInterfaceNumResources(shaderInterface)) 4054 .build(vki, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1); 4055 } 4056 4057 vk::Move<vk::VkDescriptorSet> ImageFetchRenderInstance::createDescriptorSet (const vk::DeviceInterface& vki, 4058 DescriptorUpdateMethod updateMethod, 4059 vk::VkDevice device, 4060 vk::VkDescriptorType descriptorType, 4061 ShaderInputInterface shaderInterface, 4062 vk::VkDescriptorSetLayout layout, 4063 vk::VkDescriptorPool pool, 4064 vk::VkImageView viewA, 4065 vk::VkImageView viewB, 4066 vk::DescriptorSetUpdateBuilder& updateBuilder, 4067 vk::Move<vk::VkDescriptorUpdateTemplateKHR>& updateTemplate, 4068 RawUpdateRegistry& updateRegistry, 4069 vk::VkPipelineLayout pipelineLayout) 4070 { 4071 const vk::VkDescriptorSetAllocateInfo allocInfo = 4072 { 4073 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, 4074 DE_NULL, 4075 pool, 4076 1u, 4077 &layout 4078 }; 4079 4080 vk::Move<vk::VkDescriptorSet> descriptorSet; 4081 if (updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH && updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE) 4082 { 4083 descriptorSet = allocateDescriptorSet(vki, device, &allocInfo); 4084 } 4085 else 4086 { 4087 descriptorSet = vk::Move<vk::VkDescriptorSet>(); 4088 } 4089 4090 if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_TEMPLATE) 4091 { 4092 writeDescriptorSetWithTemplate(vki, device, descriptorType, shaderInterface, layout, pool, viewA, viewB, *descriptorSet, updateTemplate, updateRegistry); 4093 } 4094 else if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE) 4095 { 4096 writeDescriptorSetWithTemplate(vki, device, descriptorType, shaderInterface, layout, pool, viewA, viewB, *descriptorSet, updateTemplate, updateRegistry, true, pipelineLayout); 4097 } 4098 else if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH) 4099 { 4100 writeDescriptorSet(vki, device, descriptorType, shaderInterface, layout, pool, viewA, viewB, *descriptorSet, updateBuilder, updateMethod); 4101 } 4102 else if (updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL) 4103 { 4104 writeDescriptorSet(vki, device, descriptorType, shaderInterface, layout, pool, viewA, viewB, *descriptorSet, updateBuilder); 4105 } 4106 return descriptorSet; 4107 } 4108 4109 void ImageFetchRenderInstance::writeDescriptorSet (const vk::DeviceInterface& vki, 4110 vk::VkDevice device, 4111 vk::VkDescriptorType descriptorType, 4112 ShaderInputInterface shaderInterface, 4113 vk::VkDescriptorSetLayout layout, 4114 vk::VkDescriptorPool pool, 4115 vk::VkImageView viewA, 4116 vk::VkImageView viewB, 4117 vk::VkDescriptorSet descriptorSet, 4118 vk::DescriptorSetUpdateBuilder& updateBuilder, 4119 DescriptorUpdateMethod updateMethod) 4120 { 4121 DE_UNREF(layout); 4122 DE_UNREF(pool); 4123 const vk::VkImageLayout imageLayout = getImageLayoutForDescriptorType(descriptorType); 4124 const vk::VkDescriptorImageInfo imageInfos[2] = 4125 { 4126 makeDescriptorImageInfo(viewA, imageLayout), 4127 makeDescriptorImageInfo(viewB, imageLayout), 4128 }; 4129 4130 switch (shaderInterface) 4131 { 4132 case SHADER_INPUT_SINGLE_DESCRIPTOR: 4133 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType, &imageInfos[0]); 4134 break; 4135 4136 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS: 4137 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType, &imageInfos[0]); 4138 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), descriptorType, &imageInfos[1]); 4139 break; 4140 4141 case SHADER_INPUT_DESCRIPTOR_ARRAY: 4142 updateBuilder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType, 2u, imageInfos); 4143 break; 4144 4145 default: 4146 DE_FATAL("Impossible"); 4147 } 4148 4149 if (updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL) 4150 { 4151 updateBuilder.update(vki, device); 4152 } 4153 } 4154 4155 void ImageFetchRenderInstance::writeDescriptorSetWithTemplate (const vk::DeviceInterface& vki, 4156 vk::VkDevice device, 4157 vk::VkDescriptorType descriptorType, 4158 ShaderInputInterface shaderInterface, 4159 vk::VkDescriptorSetLayout layout, 4160 vk::VkDescriptorPool pool, 4161 vk::VkImageView viewA, 4162 vk::VkImageView viewB, 4163 vk::VkDescriptorSet descriptorSet, 4164 vk::Move<vk::VkDescriptorUpdateTemplateKHR>& updateTemplate, 4165 RawUpdateRegistry& updateRegistry, 4166 bool withPush, 4167 vk::VkPipelineLayout pipelineLayout) 4168 { 4169 DE_UNREF(pool); 4170 std::vector<vk::VkDescriptorUpdateTemplateEntryKHR> updateEntries; 4171 vk::VkDescriptorUpdateTemplateCreateInfoKHR templateCreateInfo = 4172 { 4173 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR, 4174 DE_NULL, 4175 0, 4176 0, // updateCount 4177 DE_NULL, // pUpdates 4178 withPush ? vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR : vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR, 4179 layout, 4180 vk::VK_PIPELINE_BIND_POINT_GRAPHICS, 4181 pipelineLayout, 4182 0 4183 }; 4184 const vk::VkImageLayout imageLayout = getImageLayoutForDescriptorType(descriptorType); 4185 const vk::VkDescriptorImageInfo imageInfos[2] = 4186 { 4187 makeDescriptorImageInfo(viewA, imageLayout), 4188 makeDescriptorImageInfo(viewB, imageLayout), 4189 }; 4190 updateRegistry.addWriteObject(imageInfos[0]); 4191 updateRegistry.addWriteObject(imageInfos[1]); 4192 4193 switch (shaderInterface) 4194 { 4195 case SHADER_INPUT_SINGLE_DESCRIPTOR: 4196 updateEntries.push_back(createTemplateBinding(0, 0, 1, descriptorType, updateRegistry.getWriteObjectOffset(0), 0)); 4197 break; 4198 4199 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS: 4200 updateEntries.push_back(createTemplateBinding(0, 0, 1, descriptorType, updateRegistry.getWriteObjectOffset(0), 0)); 4201 updateEntries.push_back(createTemplateBinding(1, 0, 1, descriptorType, updateRegistry.getWriteObjectOffset(1), 0)); 4202 break; 4203 4204 case SHADER_INPUT_DESCRIPTOR_ARRAY: 4205 updateEntries.push_back(createTemplateBinding(0, 0, 2, descriptorType, updateRegistry.getWriteObjectOffset(0), sizeof(imageInfos[0]))); 4206 break; 4207 4208 default: 4209 DE_FATAL("Impossible"); 4210 } 4211 4212 templateCreateInfo.pDescriptorUpdateEntries = &updateEntries[0]; 4213 templateCreateInfo.descriptorUpdateEntryCount = (deUint32)updateEntries.size(); 4214 4215 updateTemplate = vk::createDescriptorUpdateTemplateKHR(vki, device, &templateCreateInfo); 4216 4217 if (!withPush) 4218 { 4219 vki.updateDescriptorSetWithTemplateKHR(device, descriptorSet, *updateTemplate, updateRegistry.getRawPointer()); 4220 } 4221 } 4222 4223 void ImageFetchRenderInstance::logTestPlan (void) const 4224 { 4225 std::ostringstream msg; 4226 4227 msg << "Rendering 2x2 grid.\n" 4228 << "Single descriptor set. Descriptor set contains " 4229 << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" : 4230 (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? "two" : 4231 (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" : 4232 (const char*)DE_NULL) 4233 << " descriptor(s) of type " << vk::getDescriptorTypeName(m_descriptorType) << "\n" 4234 << "Image view type is " << vk::getImageViewTypeName(m_viewType) << "\n"; 4235 4236 if (m_baseMipLevel) 4237 msg << "Image view base mip level = " << m_baseMipLevel << "\n"; 4238 if (m_baseArraySlice) 4239 msg << "Image view base array slice = " << m_baseArraySlice << "\n"; 4240 4241 if (m_stageFlags == 0u) 4242 { 4243 msg << "Descriptors are not accessed in any shader stage.\n"; 4244 } 4245 else 4246 { 4247 msg << "Color in each cell is fetched using the descriptor(s):\n"; 4248 4249 for (int resultNdx = 0; resultNdx < 4; ++resultNdx) 4250 { 4251 msg << "Test sample " << resultNdx << ": fetching at position " << m_images.getFetchPos(m_viewType, m_baseMipLevel, m_baseArraySlice, resultNdx); 4252 4253 if (m_shaderInterface != SHADER_INPUT_SINGLE_DESCRIPTOR) 4254 { 4255 const int srcResourceNdx = (resultNdx % 2); // ABAB source 4256 msg << " from descriptor " << srcResourceNdx; 4257 } 4258 4259 msg << "\n"; 4260 } 4261 4262 msg << "Descriptors are accessed in {" 4263 << (((m_stageFlags & vk::VK_SHADER_STAGE_VERTEX_BIT) != 0) ? (" vertex") : ("")) 4264 << (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0) ? (" tess_control") : ("")) 4265 << (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0) ? (" tess_evaluation") : ("")) 4266 << (((m_stageFlags & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0) ? (" geometry") : ("")) 4267 << (((m_stageFlags & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0) ? (" fragment") : ("")) 4268 << " } stages."; 4269 } 4270 4271 m_context.getTestContext().getLog() 4272 << tcu::TestLog::Message 4273 << msg.str() 4274 << tcu::TestLog::EndMessage; 4275 } 4276 4277 vk::VkPipelineLayout ImageFetchRenderInstance::getPipelineLayout (void) const 4278 { 4279 return *m_pipelineLayout; 4280 } 4281 4282 void ImageFetchRenderInstance::writeDrawCmdBuffer (vk::VkCommandBuffer cmd) const 4283 { 4284 if (m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE && m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH) 4285 { 4286 m_vki.cmdBindDescriptorSets(cmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, getPipelineLayout(), 0, 1, &m_descriptorSet.get(), 0, DE_NULL); 4287 } 4288 else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE) 4289 { 4290 m_vki.cmdPushDescriptorSetWithTemplateKHR(cmd, *m_updateTemplate, getPipelineLayout(), 0, (const void*)m_updateRegistry.getRawPointer()); 4291 } 4292 else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH) 4293 { 4294 m_updateBuilder.updateWithPush(m_vki, cmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0); 4295 } 4296 4297 m_vki.cmdDraw(cmd, 6 * 4, 1, 0, 0); // render four quads (two separate triangles) 4298 } 4299 4300 tcu::TestStatus ImageFetchRenderInstance::verifyResultImage (const tcu::ConstPixelBufferAccess& result) const 4301 { 4302 const tcu::Vec4 green (0.0f, 1.0f, 0.0f, 1.0f); 4303 const tcu::Vec4 yellow (1.0f, 1.0f, 0.0f, 1.0f); 4304 const bool doFetch = (m_stageFlags != 0u); // no active stages? Then don't fetch 4305 const tcu::Vec4 sample0 = (!doFetch) ? (yellow) : (m_images.fetchImageValue(0)); 4306 const tcu::Vec4 sample1 = (!doFetch) ? (green) : (m_images.fetchImageValue(1)); 4307 const tcu::Vec4 sample2 = (!doFetch) ? (green) : (m_images.fetchImageValue(2)); 4308 const tcu::Vec4 sample3 = (!doFetch) ? (yellow) : (m_images.fetchImageValue(3)); 4309 tcu::Surface reference (m_targetSize.x(), m_targetSize.y()); 4310 4311 drawQuadrantReferenceResult(reference.getAccess(), sample0, sample1, sample2, sample3); 4312 4313 if (!bilinearCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", reference.getAccess(), result, tcu::RGBA(1, 1, 1, 1), tcu::COMPARE_LOG_RESULT)) 4314 return tcu::TestStatus::fail("Image verification failed"); 4315 else 4316 return tcu::TestStatus::pass("Pass"); 4317 } 4318 4319 class ImageFetchComputeInstance : public vkt::TestInstance 4320 { 4321 public: 4322 ImageFetchComputeInstance (vkt::Context& context, 4323 DescriptorUpdateMethod updateMethod, 4324 vk::VkDescriptorType descriptorType, 4325 ShaderInputInterface shaderInterface, 4326 vk::VkImageViewType viewType, 4327 deUint32 baseMipLevel, 4328 deUint32 baseArraySlice); 4329 4330 private: 4331 vk::Move<vk::VkDescriptorSetLayout> createDescriptorSetLayout (void) const; 4332 vk::Move<vk::VkDescriptorPool> createDescriptorPool (void) const; 4333 vk::Move<vk::VkDescriptorSet> createDescriptorSet (vk::VkDescriptorPool pool, vk::VkDescriptorSetLayout layout); 4334 void writeDescriptorSet (vk::VkDescriptorSet descriptorSet); 4335 void writeDescriptorSetWithTemplate (vk::VkDescriptorSet descriptorSet, vk::VkDescriptorSetLayout layout, bool withPush = false, vk::VkPipelineLayout pipelineLayout = DE_NULL); 4336 4337 4338 tcu::TestStatus iterate (void); 4339 void logTestPlan (void) const; 4340 tcu::TestStatus testResourceAccess (void); 4341 4342 const DescriptorUpdateMethod m_updateMethod; 4343 const vk::VkDescriptorType m_descriptorType; 4344 const ShaderInputInterface m_shaderInterface; 4345 const vk::VkImageViewType m_viewType; 4346 const deUint32 m_baseMipLevel; 4347 const deUint32 m_baseArraySlice; 4348 vk::Move<vk::VkDescriptorUpdateTemplateKHR> m_updateTemplate; 4349 4350 const vk::DeviceInterface& m_vki; 4351 const vk::VkDevice m_device; 4352 const vk::VkQueue m_queue; 4353 const deUint32 m_queueFamilyIndex; 4354 vk::Allocator& m_allocator; 4355 4356 const ComputeInstanceResultBuffer m_result; 4357 const ImageFetchInstanceImages m_images; 4358 4359 RawUpdateRegistry m_updateRegistry; 4360 vk::DescriptorSetUpdateBuilder m_updateBuilder; 4361 }; 4362 4363 ImageFetchComputeInstance::ImageFetchComputeInstance (Context& context, 4364 DescriptorUpdateMethod updateMethod, 4365 vk::VkDescriptorType descriptorType, 4366 ShaderInputInterface shaderInterface, 4367 vk::VkImageViewType viewType, 4368 deUint32 baseMipLevel, 4369 deUint32 baseArraySlice) 4370 : vkt::TestInstance (context) 4371 , m_updateMethod (updateMethod) 4372 , m_descriptorType (descriptorType) 4373 , m_shaderInterface (shaderInterface) 4374 , m_viewType (viewType) 4375 , m_baseMipLevel (baseMipLevel) 4376 , m_baseArraySlice (baseArraySlice) 4377 , m_updateTemplate () 4378 , m_vki (context.getDeviceInterface()) 4379 , m_device (context.getDevice()) 4380 , m_queue (context.getUniversalQueue()) 4381 , m_queueFamilyIndex (context.getUniversalQueueFamilyIndex()) 4382 , m_allocator (context.getDefaultAllocator()) 4383 , m_result (m_vki, m_device, m_allocator) 4384 , m_images (m_vki, m_device, m_queueFamilyIndex, m_queue, m_allocator, m_descriptorType, m_shaderInterface, m_viewType, m_baseMipLevel, m_baseArraySlice) 4385 , m_updateRegistry () 4386 , m_updateBuilder () 4387 { 4388 } 4389 4390 vk::Move<vk::VkDescriptorSetLayout> ImageFetchComputeInstance::createDescriptorSetLayout (void) const 4391 { 4392 vk::DescriptorSetLayoutBuilder builder; 4393 vk::VkDescriptorSetLayoutCreateFlags extraFlags = 0; 4394 4395 if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE || 4396 m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH) 4397 { 4398 extraFlags |= vk::VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR; 4399 } 4400 4401 builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT); 4402 4403 switch (m_shaderInterface) 4404 { 4405 case SHADER_INPUT_SINGLE_DESCRIPTOR: 4406 builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT); 4407 break; 4408 4409 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS: 4410 builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT); 4411 builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT); 4412 break; 4413 4414 case SHADER_INPUT_DESCRIPTOR_ARRAY: 4415 builder.addArrayBinding(m_descriptorType, 2u, vk::VK_SHADER_STAGE_COMPUTE_BIT); 4416 break; 4417 4418 default: 4419 DE_FATAL("Impossible"); 4420 }; 4421 4422 return builder.build(m_vki, m_device, extraFlags); 4423 } 4424 4425 vk::Move<vk::VkDescriptorPool> ImageFetchComputeInstance::createDescriptorPool (void) const 4426 { 4427 return vk::DescriptorPoolBuilder() 4428 .addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER) 4429 .addType(m_descriptorType, getInterfaceNumResources(m_shaderInterface)) 4430 .build(m_vki, m_device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1); 4431 } 4432 4433 vk::Move<vk::VkDescriptorSet> ImageFetchComputeInstance::createDescriptorSet (vk::VkDescriptorPool pool, vk::VkDescriptorSetLayout layout) 4434 { 4435 const vk::VkDescriptorSetAllocateInfo allocInfo = 4436 { 4437 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, 4438 DE_NULL, 4439 pool, 4440 1u, 4441 &layout 4442 }; 4443 4444 vk::Move<vk::VkDescriptorSet> descriptorSet; 4445 if (m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH && m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE) 4446 { 4447 descriptorSet = allocateDescriptorSet(m_vki, m_device, &allocInfo); 4448 } 4449 else 4450 { 4451 descriptorSet = vk::Move<vk::VkDescriptorSet>(); 4452 } 4453 4454 if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_TEMPLATE) 4455 { 4456 writeDescriptorSetWithTemplate(*descriptorSet, layout); 4457 } 4458 else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL) 4459 { 4460 writeDescriptorSet(*descriptorSet); 4461 } 4462 4463 return descriptorSet; 4464 } 4465 4466 void ImageFetchComputeInstance::writeDescriptorSet (vk::VkDescriptorSet descriptorSet) 4467 { 4468 const vk::VkDescriptorBufferInfo resultInfo = vk::makeDescriptorBufferInfo(m_result.getBuffer(), 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE); 4469 const vk::VkImageLayout imageLayout = getImageLayoutForDescriptorType(m_descriptorType); 4470 const vk::VkDescriptorImageInfo imageInfos[2] = 4471 { 4472 makeDescriptorImageInfo(m_images.getImageViewA(), imageLayout), 4473 makeDescriptorImageInfo(m_images.getImageViewB(), imageLayout), 4474 }; 4475 4476 // result 4477 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultInfo); 4478 4479 // images 4480 switch (m_shaderInterface) 4481 { 4482 case SHADER_INPUT_SINGLE_DESCRIPTOR: 4483 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), m_descriptorType, &imageInfos[0]); 4484 break; 4485 4486 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS: 4487 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), m_descriptorType, &imageInfos[0]); 4488 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), m_descriptorType, &imageInfos[1]); 4489 break; 4490 4491 case SHADER_INPUT_DESCRIPTOR_ARRAY: 4492 m_updateBuilder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), m_descriptorType, 2u, imageInfos); 4493 break; 4494 4495 default: 4496 DE_FATAL("Impossible"); 4497 } 4498 4499 if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL) 4500 { 4501 m_updateBuilder.update(m_vki, m_device); 4502 } 4503 } 4504 4505 void ImageFetchComputeInstance::writeDescriptorSetWithTemplate (vk::VkDescriptorSet descriptorSet, vk::VkDescriptorSetLayout layout, bool withPush, vk::VkPipelineLayout pipelineLayout) 4506 { 4507 const vk::VkDescriptorBufferInfo resultInfo = vk::makeDescriptorBufferInfo(m_result.getBuffer(), 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE); 4508 const vk::VkImageLayout imageLayout = getImageLayoutForDescriptorType(m_descriptorType); 4509 const vk::VkDescriptorImageInfo imageInfos[2] = 4510 { 4511 makeDescriptorImageInfo(m_images.getImageViewA(), imageLayout), 4512 makeDescriptorImageInfo(m_images.getImageViewB(), imageLayout), 4513 }; 4514 std::vector<vk::VkDescriptorUpdateTemplateEntryKHR> updateEntries; 4515 vk::VkDescriptorUpdateTemplateCreateInfoKHR templateCreateInfo = 4516 { 4517 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR, 4518 DE_NULL, 4519 0, 4520 0, // updateCount 4521 DE_NULL, // pUpdates 4522 withPush ? vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR : vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR, 4523 layout, 4524 vk::VK_PIPELINE_BIND_POINT_COMPUTE, 4525 pipelineLayout, 4526 0 4527 }; 4528 4529 m_updateRegistry.addWriteObject(resultInfo); 4530 m_updateRegistry.addWriteObject(imageInfos[0]); 4531 m_updateRegistry.addWriteObject(imageInfos[1]); 4532 4533 // result 4534 updateEntries.push_back(createTemplateBinding(0u, 0, 1, vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, m_updateRegistry.getWriteObjectOffset(0), 0)); 4535 4536 // images 4537 switch (m_shaderInterface) 4538 { 4539 case SHADER_INPUT_SINGLE_DESCRIPTOR: 4540 updateEntries.push_back(createTemplateBinding(1u, 0, 1, m_descriptorType, m_updateRegistry.getWriteObjectOffset(1), 0)); 4541 break; 4542 4543 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS: 4544 updateEntries.push_back(createTemplateBinding(1u, 0, 1, m_descriptorType, m_updateRegistry.getWriteObjectOffset(1), 0)); 4545 updateEntries.push_back(createTemplateBinding(2u, 0, 1, m_descriptorType, m_updateRegistry.getWriteObjectOffset(2), 0)); 4546 break; 4547 4548 case SHADER_INPUT_DESCRIPTOR_ARRAY: 4549 updateEntries.push_back(createTemplateBinding(1u, 0, 2, m_descriptorType, m_updateRegistry.getWriteObjectOffset(1), sizeof(imageInfos[0]))); 4550 break; 4551 4552 default: 4553 DE_FATAL("Impossible"); 4554 } 4555 4556 templateCreateInfo.pDescriptorUpdateEntries = &updateEntries[0]; 4557 templateCreateInfo.descriptorUpdateEntryCount = (deUint32)updateEntries.size(); 4558 4559 m_updateTemplate = vk::createDescriptorUpdateTemplateKHR(m_vki, m_device, &templateCreateInfo); 4560 4561 if (!withPush) 4562 { 4563 m_vki.updateDescriptorSetWithTemplateKHR(m_device, descriptorSet, *m_updateTemplate, m_updateRegistry.getRawPointer()); 4564 } 4565 } 4566 4567 tcu::TestStatus ImageFetchComputeInstance::iterate (void) 4568 { 4569 logTestPlan(); 4570 return testResourceAccess(); 4571 } 4572 4573 void ImageFetchComputeInstance::logTestPlan (void) const 4574 { 4575 std::ostringstream msg; 4576 4577 msg << "Fetching 4 values from image in compute shader.\n" 4578 << "Single descriptor set. Descriptor set contains " 4579 << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" : 4580 (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? "two" : 4581 (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" : 4582 (const char*)DE_NULL) 4583 << " descriptor(s) of type " << vk::getDescriptorTypeName(m_descriptorType) << "\n" 4584 << "Image view type is " << vk::getImageViewTypeName(m_viewType) << "\n"; 4585 4586 if (m_baseMipLevel) 4587 msg << "Image view base mip level = " << m_baseMipLevel << "\n"; 4588 if (m_baseArraySlice) 4589 msg << "Image view base array slice = " << m_baseArraySlice << "\n"; 4590 4591 for (int resultNdx = 0; resultNdx < 4; ++resultNdx) 4592 { 4593 msg << "Test sample " << resultNdx << ": fetch at position " << m_images.getFetchPos(m_viewType, m_baseMipLevel, m_baseArraySlice, resultNdx); 4594 4595 if (m_shaderInterface != SHADER_INPUT_SINGLE_DESCRIPTOR) 4596 { 4597 const int srcResourceNdx = (resultNdx % 2); // ABAB source 4598 msg << " from descriptor " << srcResourceNdx; 4599 } 4600 4601 msg << "\n"; 4602 } 4603 4604 m_context.getTestContext().getLog() 4605 << tcu::TestLog::Message 4606 << msg.str() 4607 << tcu::TestLog::EndMessage; 4608 } 4609 4610 tcu::TestStatus ImageFetchComputeInstance::testResourceAccess (void) 4611 { 4612 const vk::Unique<vk::VkDescriptorSetLayout> descriptorSetLayout (createDescriptorSetLayout()); 4613 const vk::Unique<vk::VkDescriptorPool> descriptorPool (createDescriptorPool()); 4614 const vk::Unique<vk::VkDescriptorSet> descriptorSet (createDescriptorSet(*descriptorPool, *descriptorSetLayout)); 4615 const ComputePipeline pipeline (m_vki, m_device, m_context.getBinaryCollection(), 1, &descriptorSetLayout.get()); 4616 4617 const vk::VkDescriptorSet descriptorSets[] = { *descriptorSet }; 4618 const int numDescriptorSets = (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE || m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH) ? 0 : DE_LENGTH_OF_ARRAY(descriptorSets); 4619 const deUint32* const dynamicOffsets = DE_NULL; 4620 const int numDynamicOffsets = 0; 4621 const vk::VkBufferMemoryBarrier* const preBarriers = DE_NULL; 4622 const int numPreBarriers = 0; 4623 const vk::VkBufferMemoryBarrier* const postBarriers = m_result.getResultReadBarrier(); 4624 const int numPostBarriers = 1; 4625 4626 const ComputeCommand compute (m_vki, 4627 m_device, 4628 pipeline.getPipeline(), 4629 pipeline.getPipelineLayout(), 4630 tcu::UVec3(4, 1, 1), 4631 numDescriptorSets, descriptorSets, 4632 numDynamicOffsets, dynamicOffsets, 4633 numPreBarriers, preBarriers, 4634 numPostBarriers, postBarriers); 4635 4636 tcu::Vec4 results[4]; 4637 bool anyResultSet = false; 4638 bool allResultsOk = true; 4639 4640 if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE) 4641 { 4642 writeDescriptorSetWithTemplate(DE_NULL, *descriptorSetLayout, true, pipeline.getPipelineLayout()); 4643 compute.submitAndWait(m_queueFamilyIndex, m_queue, *m_updateTemplate, (const void*) m_updateRegistry.getRawPointer()); 4644 } 4645 else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH) 4646 { 4647 writeDescriptorSet(DE_NULL); 4648 compute.submitAndWait(m_queueFamilyIndex, m_queue, m_updateBuilder); 4649 } 4650 else 4651 { 4652 compute.submitAndWait(m_queueFamilyIndex, m_queue); 4653 } 4654 m_result.readResultContentsTo(&results); 4655 4656 // verify 4657 for (int resultNdx = 0; resultNdx < 4; ++resultNdx) 4658 { 4659 const tcu::Vec4 result = results[resultNdx]; 4660 const tcu::Vec4 reference = m_images.fetchImageValue(resultNdx); 4661 const tcu::Vec4 conversionThreshold = tcu::Vec4(1.0f / 255.0f); 4662 4663 if (result != tcu::Vec4(-1.0f)) 4664 anyResultSet = true; 4665 4666 if (tcu::boolAny(tcu::greaterThan(tcu::abs(result - reference), conversionThreshold))) 4667 { 4668 allResultsOk = false; 4669 4670 m_context.getTestContext().getLog() 4671 << tcu::TestLog::Message 4672 << "Test sample " << resultNdx << ": Expected " << reference << ", got " << result 4673 << tcu::TestLog::EndMessage; 4674 } 4675 } 4676 4677 // read back and verify 4678 if (allResultsOk) 4679 return tcu::TestStatus::pass("Pass"); 4680 else if (anyResultSet) 4681 return tcu::TestStatus::fail("Invalid result values"); 4682 else 4683 { 4684 m_context.getTestContext().getLog() 4685 << tcu::TestLog::Message 4686 << "Result buffer was not written to." 4687 << tcu::TestLog::EndMessage; 4688 return tcu::TestStatus::fail("Result buffer was not written to"); 4689 } 4690 } 4691 4692 class ImageSampleInstanceImages : private ImageInstanceImages 4693 { 4694 public: 4695 ImageSampleInstanceImages (const vk::DeviceInterface& vki, 4696 vk::VkDevice device, 4697 deUint32 queueFamilyIndex, 4698 vk::VkQueue queue, 4699 vk::Allocator& allocator, 4700 vk::VkDescriptorType descriptorType, 4701 ShaderInputInterface shaderInterface, 4702 vk::VkImageViewType viewType, 4703 deUint32 baseMipLevel, 4704 deUint32 baseArraySlice, 4705 bool immutable); 4706 4707 static tcu::Vec4 getSamplePos (vk::VkImageViewType viewType, deUint32 baseMipLevel, deUint32 baseArraySlice, int samplePosNdx); 4708 tcu::Vec4 fetchSampleValue (int samplePosNdx) const; 4709 4710 inline vk::VkImageView getImageViewA (void) const { return *m_imageViewA; } 4711 inline vk::VkImageView getImageViewB (void) const { return *m_imageViewB; } 4712 inline vk::VkSampler getSamplerA (void) const { return *m_samplerA; } 4713 inline vk::VkSampler getSamplerB (void) const { return *m_samplerB; } 4714 inline bool isImmutable (void) const { return m_isImmutable; } 4715 4716 private: 4717 static int getNumImages (vk::VkDescriptorType descriptorType, ShaderInputInterface shaderInterface); 4718 static tcu::Sampler createRefSampler (bool isFirst); 4719 static vk::Move<vk::VkSampler> createSampler (const vk::DeviceInterface& vki, vk::VkDevice device, const tcu::Sampler& sampler, const tcu::TextureFormat& format); 4720 4721 static tcu::Texture1DArrayView getRef1DView (const tcu::TextureLevelPyramid& source, deUint32 baseMipLevel, deUint32 baseArraySlice, std::vector<tcu::ConstPixelBufferAccess>* levelStorage); 4722 static tcu::Texture2DArrayView getRef2DView (const tcu::TextureLevelPyramid& source, deUint32 baseMipLevel, deUint32 baseArraySlice, std::vector<tcu::ConstPixelBufferAccess>* levelStorage); 4723 static tcu::Texture3DView getRef3DView (const tcu::TextureLevelPyramid& source, deUint32 baseMipLevel, deUint32 baseArraySlice, std::vector<tcu::ConstPixelBufferAccess>* levelStorage); 4724 static tcu::TextureCubeArrayView getRefCubeView (const tcu::TextureLevelPyramid& source, deUint32 baseMipLevel, deUint32 baseArraySlice, std::vector<tcu::ConstPixelBufferAccess>* levelStorage); 4725 4726 const vk::VkDescriptorType m_descriptorType; 4727 const ShaderInputInterface m_shaderInterface; 4728 const bool m_isImmutable; 4729 4730 const tcu::Sampler m_refSamplerA; 4731 const tcu::Sampler m_refSamplerB; 4732 const vk::Unique<vk::VkSampler> m_samplerA; 4733 const vk::Unique<vk::VkSampler> m_samplerB; 4734 }; 4735 4736 ImageSampleInstanceImages::ImageSampleInstanceImages (const vk::DeviceInterface& vki, 4737 vk::VkDevice device, 4738 deUint32 queueFamilyIndex, 4739 vk::VkQueue queue, 4740 vk::Allocator& allocator, 4741 vk::VkDescriptorType descriptorType, 4742 ShaderInputInterface shaderInterface, 4743 vk::VkImageViewType viewType, 4744 deUint32 baseMipLevel, 4745 deUint32 baseArraySlice, 4746 bool immutable) 4747 : ImageInstanceImages (vki, 4748 device, 4749 queueFamilyIndex, 4750 queue, 4751 allocator, 4752 descriptorType, 4753 viewType, 4754 getNumImages(descriptorType, shaderInterface), 4755 baseMipLevel, 4756 baseArraySlice) 4757 , m_descriptorType (descriptorType) 4758 , m_shaderInterface (shaderInterface) 4759 , m_isImmutable (immutable) 4760 , m_refSamplerA (createRefSampler(true)) 4761 , m_refSamplerB (createRefSampler(false)) 4762 , m_samplerA (createSampler(vki, device, m_refSamplerA, m_imageFormat)) 4763 , m_samplerB ((getInterfaceNumResources(m_shaderInterface) == 1u) 4764 ? vk::Move<vk::VkSampler>() 4765 : createSampler(vki, device, m_refSamplerB, m_imageFormat)) 4766 { 4767 } 4768 4769 tcu::Vec4 ImageSampleInstanceImages::getSamplePos (vk::VkImageViewType viewType, deUint32 baseMipLevel, deUint32 baseArraySlice, int samplePosNdx) 4770 { 4771 DE_ASSERT(de::inBounds(samplePosNdx, 0, 4)); 4772 4773 const deUint32 imageSize = (deUint32)IMAGE_SIZE >> baseMipLevel; 4774 const deUint32 arraySize = isImageViewTypeArray(viewType) ? ARRAY_SIZE - baseArraySlice : 1; 4775 4776 // choose arbitrary values that are not ambiguous with NEAREST filtering 4777 4778 switch (viewType) 4779 { 4780 case vk::VK_IMAGE_VIEW_TYPE_1D: 4781 case vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY: 4782 case vk::VK_IMAGE_VIEW_TYPE_2D: 4783 case vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY: 4784 case vk::VK_IMAGE_VIEW_TYPE_3D: 4785 { 4786 const tcu::Vec3 coords[4] = 4787 { 4788 tcu::Vec3(0.75f, 4789 0.5f, 4790 (float)(12u % imageSize) + 0.25f), 4791 4792 tcu::Vec3((float)(23u % imageSize) + 0.25f, 4793 (float)(73u % imageSize) + 0.5f, 4794 (float)(16u % imageSize) + 0.5f + (float)imageSize), 4795 4796 tcu::Vec3(-(float)(43u % imageSize) + 0.25f, 4797 (float)(84u % imageSize) + 0.5f + (float)imageSize, 4798 (float)(117u % imageSize) + 0.75f), 4799 4800 tcu::Vec3((float)imageSize + 0.5f, 4801 (float)(75u % imageSize) + 0.25f, 4802 (float)(83u % imageSize) + 0.25f + (float)imageSize), 4803 }; 4804 const deUint32 slices[4] = 4805 { 4806 0u % arraySize, 4807 4u % arraySize, 4808 9u % arraySize, 4809 2u % arraySize, 4810 }; 4811 4812 if (viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) 4813 return tcu::Vec4(coords[samplePosNdx].x() / (float)imageSize, 4814 (float)slices[samplePosNdx], 4815 0.0f, 4816 0.0f); 4817 else if (viewType == vk::VK_IMAGE_VIEW_TYPE_2D || viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY) 4818 return tcu::Vec4(coords[samplePosNdx].x() / (float)imageSize, 4819 coords[samplePosNdx].y() / (float)imageSize, 4820 (float)slices[samplePosNdx], 4821 0.0f); 4822 else if (viewType == vk::VK_IMAGE_VIEW_TYPE_3D) 4823 return tcu::Vec4(coords[samplePosNdx].x() / (float)imageSize, 4824 coords[samplePosNdx].y() / (float)imageSize, 4825 coords[samplePosNdx].z() / (float)imageSize, 4826 0.0f); 4827 else 4828 { 4829 DE_FATAL("Impossible"); 4830 return tcu::Vec4(); 4831 } 4832 } 4833 4834 case vk::VK_IMAGE_VIEW_TYPE_CUBE: 4835 case vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY: 4836 { 4837 // \note these values are in [0, texSize]*3 space for convenience 4838 const tcu::Vec3 coords[4] = 4839 { 4840 tcu::Vec3(0.75f, 4841 0.5f, 4842 (float)imageSize), 4843 4844 tcu::Vec3((float)(13u % imageSize) + 0.25f, 4845 0.0f, 4846 (float)(16u % imageSize) + 0.5f), 4847 4848 tcu::Vec3(0.0f, 4849 (float)(84u % imageSize) + 0.5f, 4850 (float)(10u % imageSize) + 0.75f), 4851 4852 tcu::Vec3((float)imageSize, 4853 (float)(75u % imageSize) + 0.25f, 4854 (float)(83u % imageSize) + 0.75f), 4855 }; 4856 const deUint32 slices[4] = 4857 { 4858 1u % arraySize, 4859 2u % arraySize, 4860 9u % arraySize, 4861 5u % arraySize, 4862 }; 4863 4864 DE_ASSERT(de::inRange(coords[samplePosNdx].x(), 0.0f, (float)imageSize)); 4865 DE_ASSERT(de::inRange(coords[samplePosNdx].y(), 0.0f, (float)imageSize)); 4866 DE_ASSERT(de::inRange(coords[samplePosNdx].z(), 0.0f, (float)imageSize)); 4867 4868 // map to [-1, 1]*3 space 4869 return tcu::Vec4(coords[samplePosNdx].x() / (float)imageSize * 2.0f - 1.0f, 4870 coords[samplePosNdx].y() / (float)imageSize * 2.0f - 1.0f, 4871 coords[samplePosNdx].z() / (float)imageSize * 2.0f - 1.0f, 4872 (float)slices[samplePosNdx]); 4873 } 4874 4875 default: 4876 DE_FATAL("Impossible"); 4877 return tcu::Vec4(); 4878 } 4879 } 4880 4881 tcu::Vec4 ImageSampleInstanceImages::fetchSampleValue (int samplePosNdx) const 4882 { 4883 DE_ASSERT(de::inBounds(samplePosNdx, 0, 4)); 4884 4885 // texture order is ABAB 4886 const bool isSamplerCase = (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER); 4887 const tcu::TextureLevelPyramid& sampleSrcA = m_sourceImageA; 4888 const tcu::TextureLevelPyramid& sampleSrcB = (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? (m_sourceImageA) : (m_sourceImageB); 4889 const tcu::TextureLevelPyramid& sampleSrc = (isSamplerCase) ? (sampleSrcA) : ((samplePosNdx % 2) == 0) ? (sampleSrcA) : (sampleSrcB); 4890 4891 // sampler order is ABAB 4892 const tcu::Sampler& samplerA = m_refSamplerA; 4893 const tcu::Sampler& samplerB = (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? (m_refSamplerA) : (m_refSamplerB); 4894 const tcu::Sampler& sampler = ((samplePosNdx % 2) == 0) ? (samplerA) : (samplerB); 4895 4896 const tcu::Vec4 samplePos = getSamplePos(m_viewType, m_baseMipLevel, m_baseArraySlice, samplePosNdx); 4897 const float lod = 0.0f; 4898 std::vector<tcu::ConstPixelBufferAccess> levelStorage; 4899 4900 switch (m_viewType) 4901 { 4902 case vk::VK_IMAGE_VIEW_TYPE_1D: 4903 case vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY: return getRef1DView(sampleSrc, m_baseMipLevel, m_baseArraySlice, &levelStorage).sample(sampler, samplePos.x(), samplePos.y(), lod); 4904 case vk::VK_IMAGE_VIEW_TYPE_2D: 4905 case vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY: return getRef2DView(sampleSrc, m_baseMipLevel, m_baseArraySlice, &levelStorage).sample(sampler, samplePos.x(), samplePos.y(), samplePos.z(), lod); 4906 case vk::VK_IMAGE_VIEW_TYPE_3D: return getRef3DView(sampleSrc, m_baseMipLevel, m_baseArraySlice, &levelStorage).sample(sampler, samplePos.x(), samplePos.y(), samplePos.z(), lod); 4907 case vk::VK_IMAGE_VIEW_TYPE_CUBE: 4908 case vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY: return getRefCubeView(sampleSrc, m_baseMipLevel, m_baseArraySlice, &levelStorage).sample(sampler, samplePos.x(), samplePos.y(), samplePos.z(), samplePos.w(), lod); 4909 4910 default: 4911 { 4912 DE_FATAL("Impossible"); 4913 return tcu::Vec4(); 4914 } 4915 } 4916 } 4917 4918 int ImageSampleInstanceImages::getNumImages (vk::VkDescriptorType descriptorType, ShaderInputInterface shaderInterface) 4919 { 4920 // If we are testing separate samplers, just one image is enough 4921 if (descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER) 4922 return 1; 4923 else if (descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) 4924 { 4925 // combined: numImages == numSamplers 4926 return getInterfaceNumResources(shaderInterface); 4927 } 4928 else 4929 { 4930 DE_FATAL("Impossible"); 4931 return 0; 4932 } 4933 } 4934 4935 tcu::Sampler ImageSampleInstanceImages::createRefSampler (bool isFirst) 4936 { 4937 if (isFirst) 4938 { 4939 // linear, wrapping 4940 return tcu::Sampler(tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, tcu::Sampler::LINEAR, tcu::Sampler::LINEAR); 4941 } 4942 else 4943 { 4944 // nearest, clamping 4945 return tcu::Sampler(tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::NEAREST, tcu::Sampler::NEAREST); 4946 } 4947 } 4948 4949 vk::Move<vk::VkSampler> ImageSampleInstanceImages::createSampler (const vk::DeviceInterface& vki, vk::VkDevice device, const tcu::Sampler& sampler, const tcu::TextureFormat& format) 4950 { 4951 const vk::VkSamplerCreateInfo createInfo = vk::mapSampler(sampler, format); 4952 4953 return vk::createSampler(vki, device, &createInfo); 4954 } 4955 4956 tcu::Texture1DArrayView ImageSampleInstanceImages::getRef1DView (const tcu::TextureLevelPyramid& source, deUint32 baseMipLevel, deUint32 baseArraySlice, std::vector<tcu::ConstPixelBufferAccess>* levelStorage) 4957 { 4958 DE_ASSERT(levelStorage->empty()); 4959 4960 const deUint32 numSlices = (deUint32)source.getLevel(0).getHeight(); 4961 const deUint32 numLevels = (deUint32)source.getNumLevels(); 4962 4963 // cut pyramid from baseMipLevel 4964 for (deUint32 level = baseMipLevel; level < numLevels; ++level) 4965 { 4966 // cut levels from baseArraySlice 4967 const tcu::ConstPixelBufferAccess wholeLevel = source.getLevel(level); 4968 const tcu::ConstPixelBufferAccess cutLevel = tcu::getSubregion(wholeLevel, 0, baseArraySlice, wholeLevel.getWidth(), numSlices - baseArraySlice); 4969 levelStorage->push_back(cutLevel); 4970 } 4971 4972 return tcu::Texture1DArrayView((int)levelStorage->size(), &levelStorage->front()); 4973 } 4974 4975 tcu::Texture2DArrayView ImageSampleInstanceImages::getRef2DView (const tcu::TextureLevelPyramid& source, deUint32 baseMipLevel, deUint32 baseArraySlice, std::vector<tcu::ConstPixelBufferAccess>* levelStorage) 4976 { 4977 DE_ASSERT(levelStorage->empty()); 4978 4979 const deUint32 numSlices = (deUint32)source.getLevel(0).getDepth(); 4980 const deUint32 numLevels = (deUint32)source.getNumLevels(); 4981 4982 // cut pyramid from baseMipLevel 4983 for (deUint32 level = baseMipLevel; level < numLevels; ++level) 4984 { 4985 // cut levels from baseArraySlice 4986 const tcu::ConstPixelBufferAccess wholeLevel = source.getLevel(level); 4987 const tcu::ConstPixelBufferAccess cutLevel = tcu::getSubregion(wholeLevel, 0, 0, baseArraySlice, wholeLevel.getWidth(), wholeLevel.getHeight(), numSlices - baseArraySlice); 4988 levelStorage->push_back(cutLevel); 4989 } 4990 4991 return tcu::Texture2DArrayView((int)levelStorage->size(), &levelStorage->front()); 4992 } 4993 4994 tcu::Texture3DView ImageSampleInstanceImages::getRef3DView (const tcu::TextureLevelPyramid& source, deUint32 baseMipLevel, deUint32 baseArraySlice, std::vector<tcu::ConstPixelBufferAccess>* levelStorage) 4995 { 4996 DE_ASSERT(levelStorage->empty()); 4997 DE_ASSERT(baseArraySlice == 0); 4998 DE_UNREF(baseArraySlice); 4999 5000 const deUint32 numLevels = (deUint32)source.getNumLevels(); 5001 5002 // cut pyramid from baseMipLevel 5003 for (deUint32 level = baseMipLevel; level < numLevels; ++level) 5004 levelStorage->push_back(source.getLevel(level)); 5005 5006 return tcu::Texture3DView((int)levelStorage->size(), &levelStorage->front()); 5007 } 5008 5009 tcu::TextureCubeArrayView ImageSampleInstanceImages::getRefCubeView (const tcu::TextureLevelPyramid& source, deUint32 baseMipLevel, deUint32 baseArraySlice, std::vector<tcu::ConstPixelBufferAccess>* levelStorage) 5010 { 5011 DE_ASSERT(levelStorage->empty()); 5012 5013 const deUint32 numSlices = (deUint32)source.getLevel(0).getDepth() / 6; 5014 const deUint32 numLevels = (deUint32)source.getNumLevels(); 5015 5016 // cut pyramid from baseMipLevel 5017 for (deUint32 level = baseMipLevel; level < numLevels; ++level) 5018 { 5019 // cut levels from baseArraySlice 5020 const tcu::ConstPixelBufferAccess wholeLevel = source.getLevel(level); 5021 const tcu::ConstPixelBufferAccess cutLevel = tcu::getSubregion(wholeLevel, 0, 0, baseArraySlice * 6, wholeLevel.getWidth(), wholeLevel.getHeight(), (numSlices - baseArraySlice) * 6); 5022 levelStorage->push_back(cutLevel); 5023 } 5024 5025 return tcu::TextureCubeArrayView((int)levelStorage->size(), &levelStorage->front()); 5026 } 5027 5028 class ImageSampleRenderInstance : public SingleCmdRenderInstance 5029 { 5030 public: 5031 ImageSampleRenderInstance (vkt::Context& context, 5032 DescriptorUpdateMethod updateMethod, 5033 bool isPrimaryCmdBuf, 5034 vk::VkDescriptorType descriptorType, 5035 vk::VkShaderStageFlags stageFlags, 5036 ShaderInputInterface shaderInterface, 5037 vk::VkImageViewType viewType, 5038 deUint32 baseMipLevel, 5039 deUint32 baseArraySlice, 5040 bool isImmutable); 5041 5042 private: 5043 static vk::Move<vk::VkDescriptorSetLayout> createDescriptorSetLayout (const vk::DeviceInterface& vki, 5044 vk::VkDevice device, 5045 vk::VkDescriptorType descriptorType, 5046 ShaderInputInterface shaderInterface, 5047 vk::VkShaderStageFlags stageFlags, 5048 const ImageSampleInstanceImages& images, 5049 DescriptorUpdateMethod updateMethod); 5050 5051 static vk::Move<vk::VkPipelineLayout> createPipelineLayout (const vk::DeviceInterface& vki, 5052 vk::VkDevice device, 5053 vk::VkDescriptorSetLayout descriptorSetLayout); 5054 5055 static vk::Move<vk::VkDescriptorPool> createDescriptorPool (const vk::DeviceInterface& vki, 5056 vk::VkDevice device, 5057 vk::VkDescriptorType descriptorType, 5058 ShaderInputInterface shaderInterface); 5059 5060 static vk::Move<vk::VkDescriptorSet> createDescriptorSet (const vk::DeviceInterface& vki, 5061 DescriptorUpdateMethod updateMethod, 5062 vk::VkDevice device, 5063 vk::VkDescriptorType descriptorType, 5064 ShaderInputInterface shaderInterface, 5065 vk::VkDescriptorSetLayout layout, 5066 vk::VkDescriptorPool pool, 5067 bool isImmutable, 5068 const ImageSampleInstanceImages& images, 5069 vk::DescriptorSetUpdateBuilder& updateBuilder, 5070 vk::Move<vk::VkDescriptorUpdateTemplateKHR>& updateTemplate, 5071 RawUpdateRegistry& updateRegistry, 5072 vk::VkPipelineLayout pipelineLayout = DE_NULL); 5073 5074 static void writeSamplerDescriptorSet (const vk::DeviceInterface& vki, 5075 vk::VkDevice device, 5076 ShaderInputInterface shaderInterface, 5077 bool isImmutable, 5078 const ImageSampleInstanceImages& images, 5079 vk::VkDescriptorSet descriptorSet, 5080 vk::DescriptorSetUpdateBuilder& updateBuilder, 5081 DescriptorUpdateMethod updateMethod = DESCRIPTOR_UPDATE_METHOD_NORMAL); 5082 5083 static void writeImageSamplerDescriptorSet (const vk::DeviceInterface& vki, 5084 vk::VkDevice device, 5085 ShaderInputInterface shaderInterface, 5086 bool isImmutable, 5087 const ImageSampleInstanceImages& images, 5088 vk::VkDescriptorSet descriptorSet, 5089 vk::DescriptorSetUpdateBuilder& updateBuilder, 5090 DescriptorUpdateMethod updateMethod = DESCRIPTOR_UPDATE_METHOD_NORMAL); 5091 5092 static void writeSamplerDescriptorSetWithTemplate (const vk::DeviceInterface& vki, 5093 vk::VkDevice device, 5094 ShaderInputInterface shaderInterface, 5095 bool isImmutable, 5096 const ImageSampleInstanceImages& images, 5097 vk::VkDescriptorSet descriptorSet, 5098 vk::VkDescriptorSetLayout layout, 5099 vk::Move<vk::VkDescriptorUpdateTemplateKHR>& updateTemplate, 5100 RawUpdateRegistry& updateRegistry, 5101 bool withPush = false, 5102 vk::VkPipelineLayout pipelineLayout = 0); 5103 5104 static void writeImageSamplerDescriptorSetWithTemplate (const vk::DeviceInterface& vki, 5105 vk::VkDevice device, 5106 ShaderInputInterface shaderInterface, 5107 bool isImmutable, 5108 const ImageSampleInstanceImages& images, 5109 vk::VkDescriptorSet descriptorSet, 5110 vk::VkDescriptorSetLayout layout, 5111 vk::Move<vk::VkDescriptorUpdateTemplateKHR>& updateTemplate, 5112 RawUpdateRegistry& updateRegistry, 5113 bool withPush = false, 5114 vk::VkPipelineLayout pipelineLayout = 0); 5115 5116 void logTestPlan (void) const; 5117 vk::VkPipelineLayout getPipelineLayout (void) const; 5118 void writeDrawCmdBuffer (vk::VkCommandBuffer cmd) const; 5119 tcu::TestStatus verifyResultImage (const tcu::ConstPixelBufferAccess& result) const; 5120 5121 enum 5122 { 5123 RENDER_SIZE = 128, 5124 }; 5125 5126 const DescriptorUpdateMethod m_updateMethod; 5127 const vk::VkDescriptorType m_descriptorType; 5128 const vk::VkShaderStageFlags m_stageFlags; 5129 const ShaderInputInterface m_shaderInterface; 5130 const vk::VkImageViewType m_viewType; 5131 const deUint32 m_baseMipLevel; 5132 const deUint32 m_baseArraySlice; 5133 5134 vk::Move<vk::VkDescriptorUpdateTemplateKHR> m_updateTemplate; 5135 RawUpdateRegistry m_updateRegistry; 5136 vk::DescriptorSetUpdateBuilder m_updateBuilder; 5137 const ImageSampleInstanceImages m_images; 5138 const vk::Unique<vk::VkDescriptorSetLayout> m_descriptorSetLayout; 5139 const vk::Unique<vk::VkPipelineLayout> m_pipelineLayout; 5140 const vk::Unique<vk::VkDescriptorPool> m_descriptorPool; 5141 const vk::Unique<vk::VkDescriptorSet> m_descriptorSet; 5142 }; 5143 5144 ImageSampleRenderInstance::ImageSampleRenderInstance (vkt::Context& context, 5145 DescriptorUpdateMethod updateMethod, 5146 bool isPrimaryCmdBuf, 5147 vk::VkDescriptorType descriptorType, 5148 vk::VkShaderStageFlags stageFlags, 5149 ShaderInputInterface shaderInterface, 5150 vk::VkImageViewType viewType, 5151 deUint32 baseMipLevel, 5152 deUint32 baseArraySlice, 5153 bool isImmutable) 5154 : SingleCmdRenderInstance (context, isPrimaryCmdBuf, tcu::UVec2(RENDER_SIZE, RENDER_SIZE)) 5155 , m_updateMethod (updateMethod) 5156 , m_descriptorType (descriptorType) 5157 , m_stageFlags (stageFlags) 5158 , m_shaderInterface (shaderInterface) 5159 , m_viewType (viewType) 5160 , m_baseMipLevel (baseMipLevel) 5161 , m_baseArraySlice (baseArraySlice) 5162 , m_updateTemplate () 5163 , m_updateRegistry () 5164 , m_updateBuilder () 5165 , m_images (m_vki, m_device, m_queueFamilyIndex, m_queue, m_allocator, m_descriptorType, m_shaderInterface, m_viewType, m_baseMipLevel, m_baseArraySlice, isImmutable) 5166 , m_descriptorSetLayout (createDescriptorSetLayout(m_vki, m_device, m_descriptorType, m_shaderInterface, m_stageFlags, m_images, m_updateMethod)) 5167 , m_pipelineLayout (createPipelineLayout(m_vki, m_device, *m_descriptorSetLayout)) 5168 , m_descriptorPool (createDescriptorPool(m_vki, m_device, m_descriptorType, m_shaderInterface)) 5169 , m_descriptorSet (createDescriptorSet(m_vki, m_updateMethod, m_device, m_descriptorType, m_shaderInterface, *m_descriptorSetLayout, *m_descriptorPool, isImmutable, m_images, m_updateBuilder, m_updateTemplate, m_updateRegistry, *m_pipelineLayout)) 5170 { 5171 } 5172 5173 vk::Move<vk::VkDescriptorSetLayout> ImageSampleRenderInstance::createDescriptorSetLayout (const vk::DeviceInterface& vki, 5174 vk::VkDevice device, 5175 vk::VkDescriptorType descriptorType, 5176 ShaderInputInterface shaderInterface, 5177 vk::VkShaderStageFlags stageFlags, 5178 const ImageSampleInstanceImages& images, 5179 DescriptorUpdateMethod updateMethod) 5180 { 5181 const vk::VkSampler samplers[2] = 5182 { 5183 images.getSamplerA(), 5184 images.getSamplerB(), 5185 }; 5186 5187 vk::DescriptorSetLayoutBuilder builder; 5188 const bool addSeparateImage = descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER; 5189 vk::VkDescriptorSetLayoutCreateFlags extraFlags = 0; 5190 5191 if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE || 5192 updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH) 5193 { 5194 extraFlags |= vk::VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR; 5195 } 5196 5197 // (combined)samplers follow 5198 switch (shaderInterface) 5199 { 5200 case SHADER_INPUT_SINGLE_DESCRIPTOR: 5201 if (addSeparateImage) 5202 builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, stageFlags); 5203 builder.addSingleSamplerBinding(descriptorType, stageFlags, (images.isImmutable()) ? (&samplers[0]) : (DE_NULL)); 5204 break; 5205 5206 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS: 5207 if (addSeparateImage) 5208 builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, stageFlags); 5209 builder.addSingleSamplerBinding(descriptorType, stageFlags, (images.isImmutable()) ? (&samplers[0]) : (DE_NULL)); 5210 builder.addSingleSamplerBinding(descriptorType, stageFlags, (images.isImmutable()) ? (&samplers[1]) : (DE_NULL)); 5211 break; 5212 5213 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS: 5214 builder.addSingleSamplerBinding(descriptorType, stageFlags, (images.isImmutable()) ? (&samplers[0]) : (DE_NULL)); 5215 if (addSeparateImage) 5216 builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, stageFlags); 5217 builder.addSingleSamplerBinding(descriptorType, stageFlags, (images.isImmutable()) ? (&samplers[1]) : (DE_NULL)); 5218 break; 5219 5220 case SHADER_INPUT_DESCRIPTOR_ARRAY: 5221 if (addSeparateImage) 5222 builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, stageFlags); 5223 builder.addArraySamplerBinding(descriptorType, 2u, stageFlags, (images.isImmutable()) ? (samplers) : (DE_NULL)); 5224 break; 5225 5226 default: 5227 DE_FATAL("Impossible"); 5228 } 5229 5230 return builder.build(vki, device, extraFlags); 5231 } 5232 5233 vk::Move<vk::VkPipelineLayout> ImageSampleRenderInstance::createPipelineLayout (const vk::DeviceInterface& vki, 5234 vk::VkDevice device, 5235 vk::VkDescriptorSetLayout descriptorSetLayout) 5236 { 5237 const vk::VkPipelineLayoutCreateInfo createInfo = 5238 { 5239 vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, 5240 DE_NULL, 5241 (vk::VkPipelineLayoutCreateFlags)0, 5242 1, // descriptorSetCount 5243 &descriptorSetLayout, // pSetLayouts 5244 0u, // pushConstantRangeCount 5245 DE_NULL, // pPushConstantRanges 5246 }; 5247 return vk::createPipelineLayout(vki, device, &createInfo); 5248 } 5249 5250 vk::Move<vk::VkDescriptorPool> ImageSampleRenderInstance::createDescriptorPool (const vk::DeviceInterface& vki, 5251 vk::VkDevice device, 5252 vk::VkDescriptorType descriptorType, 5253 ShaderInputInterface shaderInterface) 5254 { 5255 vk::DescriptorPoolBuilder builder; 5256 5257 if (descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER) 5258 { 5259 // separate samplers need image to sample 5260 builder.addType(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE); 5261 5262 // also need sample to use, indifferent of whether immutable or not 5263 builder.addType(vk::VK_DESCRIPTOR_TYPE_SAMPLER, getInterfaceNumResources(shaderInterface)); 5264 } 5265 else if (descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) 5266 { 5267 // combined image samplers 5268 builder.addType(vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, getInterfaceNumResources(shaderInterface)); 5269 } 5270 else 5271 DE_FATAL("Impossible"); 5272 5273 return builder.build(vki, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1); 5274 } 5275 5276 vk::Move<vk::VkDescriptorSet> ImageSampleRenderInstance::createDescriptorSet (const vk::DeviceInterface& vki, 5277 DescriptorUpdateMethod updateMethod, 5278 vk::VkDevice device, 5279 vk::VkDescriptorType descriptorType, 5280 ShaderInputInterface shaderInterface, 5281 vk::VkDescriptorSetLayout layout, 5282 vk::VkDescriptorPool pool, 5283 bool isImmutable, 5284 const ImageSampleInstanceImages& images, 5285 vk::DescriptorSetUpdateBuilder& updateBuilder, 5286 vk::Move<vk::VkDescriptorUpdateTemplateKHR>& updateTemplate, 5287 RawUpdateRegistry& updateRegistry, 5288 vk::VkPipelineLayout pipelineLayout) 5289 { 5290 const vk::VkDescriptorSetAllocateInfo allocInfo = 5291 { 5292 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, 5293 DE_NULL, 5294 pool, 5295 1u, 5296 &layout 5297 }; 5298 5299 vk::Move<vk::VkDescriptorSet> descriptorSet; 5300 if (updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH && updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE) 5301 { 5302 descriptorSet = allocateDescriptorSet(vki, device, &allocInfo); 5303 } 5304 else 5305 { 5306 descriptorSet = vk::Move<vk::VkDescriptorSet>(); 5307 } 5308 5309 if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_TEMPLATE) 5310 { 5311 if (descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER) 5312 writeSamplerDescriptorSetWithTemplate(vki, device, shaderInterface, isImmutable, images, *descriptorSet, layout, updateTemplate, updateRegistry); 5313 else if (descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) 5314 writeImageSamplerDescriptorSetWithTemplate(vki, device, shaderInterface, isImmutable, images, *descriptorSet, layout, updateTemplate, updateRegistry); 5315 else 5316 DE_FATAL("Impossible"); 5317 } 5318 else if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE) 5319 { 5320 if (descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER) 5321 writeSamplerDescriptorSetWithTemplate(vki, device, shaderInterface, isImmutable, images, DE_NULL, layout, updateTemplate, updateRegistry, true, pipelineLayout); 5322 else if (descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) 5323 writeImageSamplerDescriptorSetWithTemplate(vki, device, shaderInterface, isImmutable, images, DE_NULL, layout, updateTemplate, updateRegistry, true, pipelineLayout); 5324 else 5325 DE_FATAL("Impossible"); 5326 } 5327 else if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH) 5328 { 5329 if (descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER) 5330 writeSamplerDescriptorSet(vki, device, shaderInterface, isImmutable, images, *descriptorSet, updateBuilder, updateMethod); 5331 else if (descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) 5332 writeImageSamplerDescriptorSet(vki, device, shaderInterface, isImmutable, images, *descriptorSet, updateBuilder, updateMethod); 5333 else 5334 DE_FATAL("Impossible"); 5335 } 5336 else if (updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL) 5337 { 5338 if (descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER) 5339 writeSamplerDescriptorSet(vki, device, shaderInterface, isImmutable, images, *descriptorSet, updateBuilder); 5340 else if (descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) 5341 writeImageSamplerDescriptorSet(vki, device, shaderInterface, isImmutable, images, *descriptorSet, updateBuilder); 5342 else 5343 DE_FATAL("Impossible"); 5344 } 5345 5346 return descriptorSet; 5347 } 5348 5349 void ImageSampleRenderInstance::writeSamplerDescriptorSet (const vk::DeviceInterface& vki, 5350 vk::VkDevice device, 5351 ShaderInputInterface shaderInterface, 5352 bool isImmutable, 5353 const ImageSampleInstanceImages& images, 5354 vk::VkDescriptorSet descriptorSet, 5355 vk::DescriptorSetUpdateBuilder& updateBuilder, 5356 DescriptorUpdateMethod updateMethod) 5357 { 5358 const vk::VkDescriptorImageInfo imageInfo = makeDescriptorImageInfo(images.getImageViewA(), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); 5359 const vk::VkDescriptorImageInfo samplersInfos[2] = 5360 { 5361 makeDescriptorImageInfo(images.getSamplerA()), 5362 makeDescriptorImageInfo(images.getSamplerB()), 5363 }; 5364 5365 const deUint32 samplerLocation = shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS ? 1u : 0u; 5366 5367 // stand alone texture 5368 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(samplerLocation), vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, &imageInfo); 5369 5370 // samplers 5371 if (!isImmutable || (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)) 5372 { 5373 switch (shaderInterface) 5374 { 5375 case SHADER_INPUT_SINGLE_DESCRIPTOR: 5376 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[0]); 5377 break; 5378 5379 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS: 5380 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[0]); 5381 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[1]); 5382 break; 5383 5384 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS: 5385 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[0]); 5386 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[1]); 5387 break; 5388 5389 case SHADER_INPUT_DESCRIPTOR_ARRAY: 5390 updateBuilder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_SAMPLER, 2u, samplersInfos); 5391 break; 5392 5393 default: 5394 DE_FATAL("Impossible"); 5395 } 5396 } 5397 5398 if (updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL) 5399 { 5400 updateBuilder.update(vki, device); 5401 } 5402 } 5403 5404 void ImageSampleRenderInstance::writeImageSamplerDescriptorSet (const vk::DeviceInterface& vki, 5405 vk::VkDevice device, 5406 ShaderInputInterface shaderInterface, 5407 bool isImmutable, 5408 const ImageSampleInstanceImages& images, 5409 vk::VkDescriptorSet descriptorSet, 5410 vk::DescriptorSetUpdateBuilder& updateBuilder, 5411 DescriptorUpdateMethod updateMethod) 5412 { 5413 const vk::VkSampler samplers[2] = 5414 { 5415 (isImmutable && updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH) ? (0) : (images.getSamplerA()), 5416 (isImmutable && updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH) ? (0) : (images.getSamplerB()), 5417 }; 5418 const vk::VkDescriptorImageInfo imageSamplers[2] = 5419 { 5420 vk::makeDescriptorImageInfo(samplers[0], images.getImageViewA(), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL), 5421 vk::makeDescriptorImageInfo(samplers[1], images.getImageViewB(), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL), 5422 }; 5423 5424 // combined image samplers 5425 switch (shaderInterface) 5426 { 5427 case SHADER_INPUT_SINGLE_DESCRIPTOR: 5428 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[0]); 5429 break; 5430 5431 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS: 5432 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[0]); 5433 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[1]); 5434 break; 5435 5436 case SHADER_INPUT_DESCRIPTOR_ARRAY: 5437 updateBuilder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2u, imageSamplers); 5438 break; 5439 5440 default: 5441 DE_FATAL("Impossible"); 5442 } 5443 5444 if (updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL) 5445 { 5446 updateBuilder.update(vki, device); 5447 } 5448 } 5449 5450 void ImageSampleRenderInstance::writeSamplerDescriptorSetWithTemplate (const vk::DeviceInterface& vki, 5451 vk::VkDevice device, 5452 ShaderInputInterface shaderInterface, 5453 bool isImmutable, 5454 const ImageSampleInstanceImages& images, 5455 vk::VkDescriptorSet descriptorSet, 5456 vk::VkDescriptorSetLayout layout, 5457 vk::Move<vk::VkDescriptorUpdateTemplateKHR>& updateTemplate, 5458 RawUpdateRegistry& updateRegistry, 5459 bool withPush, 5460 vk::VkPipelineLayout pipelineLayout) 5461 { 5462 const vk::VkDescriptorImageInfo imageInfo = makeDescriptorImageInfo(images.getImageViewA(), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); 5463 const vk::VkDescriptorImageInfo samplersInfos[2] = 5464 { 5465 makeDescriptorImageInfo(images.getSamplerA()), 5466 makeDescriptorImageInfo(images.getSamplerB()), 5467 }; 5468 5469 const deUint32 samplerLocation = shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS ? 1u : 0u; 5470 5471 std::vector<vk::VkDescriptorUpdateTemplateEntryKHR> updateEntries; 5472 vk::VkDescriptorUpdateTemplateCreateInfoKHR templateCreateInfo = 5473 { 5474 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR, 5475 DE_NULL, 5476 0, 5477 0, // updateCount 5478 DE_NULL, // pUpdates 5479 withPush ? vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR : vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR, 5480 layout, 5481 vk::VK_PIPELINE_BIND_POINT_GRAPHICS, 5482 pipelineLayout, 5483 0 5484 }; 5485 updateRegistry.addWriteObject(imageInfo); 5486 updateRegistry.addWriteObject(samplersInfos[0]); 5487 updateRegistry.addWriteObject(samplersInfos[1]); 5488 5489 // stand alone texture 5490 updateEntries.push_back(createTemplateBinding(samplerLocation, 0, 1, vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, updateRegistry.getWriteObjectOffset(0), 0)); 5491 5492 // samplers 5493 if (!isImmutable || withPush) 5494 { 5495 switch (shaderInterface) 5496 { 5497 case SHADER_INPUT_SINGLE_DESCRIPTOR: 5498 updateEntries.push_back(createTemplateBinding(1, 0, 1, vk::VK_DESCRIPTOR_TYPE_SAMPLER, updateRegistry.getWriteObjectOffset(1), 0)); 5499 break; 5500 5501 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS: 5502 updateEntries.push_back(createTemplateBinding(1, 0, 1, vk::VK_DESCRIPTOR_TYPE_SAMPLER, updateRegistry.getWriteObjectOffset(1), 0)); 5503 updateEntries.push_back(createTemplateBinding(2, 0, 1, vk::VK_DESCRIPTOR_TYPE_SAMPLER, updateRegistry.getWriteObjectOffset(2), 0)); 5504 break; 5505 5506 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS: 5507 updateEntries.push_back(createTemplateBinding(0, 0, 1, vk::VK_DESCRIPTOR_TYPE_SAMPLER, updateRegistry.getWriteObjectOffset(1), 0)); 5508 updateEntries.push_back(createTemplateBinding(2, 0, 1, vk::VK_DESCRIPTOR_TYPE_SAMPLER, updateRegistry.getWriteObjectOffset(2), 0)); 5509 break; 5510 5511 case SHADER_INPUT_DESCRIPTOR_ARRAY: 5512 updateEntries.push_back(createTemplateBinding(1, 0, 2, vk::VK_DESCRIPTOR_TYPE_SAMPLER, updateRegistry.getWriteObjectOffset(1), sizeof(samplersInfos[0]))); 5513 break; 5514 5515 default: 5516 DE_FATAL("Impossible"); 5517 } 5518 } 5519 5520 templateCreateInfo.pDescriptorUpdateEntries = &updateEntries[0]; 5521 templateCreateInfo.descriptorUpdateEntryCount = (deUint32)updateEntries.size(); 5522 5523 updateTemplate = vk::createDescriptorUpdateTemplateKHR(vki, device, &templateCreateInfo); 5524 5525 if (!withPush) 5526 { 5527 vki.updateDescriptorSetWithTemplateKHR(device, descriptorSet, *updateTemplate, updateRegistry.getRawPointer()); 5528 } 5529 5530 } 5531 5532 void ImageSampleRenderInstance::writeImageSamplerDescriptorSetWithTemplate (const vk::DeviceInterface& vki, 5533 vk::VkDevice device, 5534 ShaderInputInterface shaderInterface, 5535 bool isImmutable, 5536 const ImageSampleInstanceImages& images, 5537 vk::VkDescriptorSet descriptorSet, 5538 vk::VkDescriptorSetLayout layout, 5539 vk::Move<vk::VkDescriptorUpdateTemplateKHR>& updateTemplate, 5540 RawUpdateRegistry& updateRegistry, 5541 bool withPush, 5542 vk::VkPipelineLayout pipelineLayout) 5543 { 5544 const vk::VkSampler samplers[2] = 5545 { 5546 (isImmutable && !withPush) ? (0) : (images.getSamplerA()), 5547 (isImmutable && !withPush) ? (0) : (images.getSamplerB()), 5548 }; 5549 const vk::VkDescriptorImageInfo imageSamplers[2] = 5550 { 5551 vk::makeDescriptorImageInfo(samplers[0], images.getImageViewA(), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL), 5552 vk::makeDescriptorImageInfo(samplers[1], images.getImageViewB(), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL), 5553 }; 5554 5555 std::vector<vk::VkDescriptorUpdateTemplateEntryKHR> updateEntries; 5556 vk::VkDescriptorUpdateTemplateCreateInfoKHR templateCreateInfo = 5557 { 5558 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR, 5559 DE_NULL, 5560 0, 5561 0, // updateCount 5562 DE_NULL, // pUpdates 5563 withPush ? vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR : vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR, 5564 layout, 5565 vk::VK_PIPELINE_BIND_POINT_GRAPHICS, 5566 pipelineLayout, 5567 0 5568 }; 5569 updateRegistry.addWriteObject(imageSamplers[0]); 5570 updateRegistry.addWriteObject(imageSamplers[1]); 5571 5572 // combined image samplers 5573 switch (shaderInterface) 5574 { 5575 case SHADER_INPUT_SINGLE_DESCRIPTOR: 5576 updateEntries.push_back(createTemplateBinding(0, 0, 1, vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, updateRegistry.getWriteObjectOffset(0), 0)); 5577 break; 5578 5579 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS: 5580 updateEntries.push_back(createTemplateBinding(0, 0, 1, vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, updateRegistry.getWriteObjectOffset(0), 0)); 5581 updateEntries.push_back(createTemplateBinding(1, 0, 1, vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, updateRegistry.getWriteObjectOffset(1), 0)); 5582 break; 5583 5584 case SHADER_INPUT_DESCRIPTOR_ARRAY: 5585 updateEntries.push_back(createTemplateBinding(0, 0, 2, vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, updateRegistry.getWriteObjectOffset(0), sizeof(imageSamplers[0]))); 5586 break; 5587 5588 default: 5589 DE_FATAL("Impossible"); 5590 } 5591 5592 templateCreateInfo.pDescriptorUpdateEntries = &updateEntries[0]; 5593 templateCreateInfo.descriptorUpdateEntryCount = (deUint32)updateEntries.size(); 5594 5595 updateTemplate = vk::createDescriptorUpdateTemplateKHR(vki, device, &templateCreateInfo); 5596 5597 if (!withPush) 5598 { 5599 vki.updateDescriptorSetWithTemplateKHR(device, descriptorSet, *updateTemplate, updateRegistry.getRawPointer()); 5600 } 5601 } 5602 5603 void ImageSampleRenderInstance::logTestPlan (void) const 5604 { 5605 std::ostringstream msg; 5606 5607 msg << "Rendering 2x2 grid.\n"; 5608 5609 if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER) 5610 { 5611 msg << "Single descriptor set. Descriptor set contains " 5612 << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" : 5613 (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? "two" : 5614 (m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) ? "two" : 5615 (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" : 5616 (const char*)DE_NULL) 5617 << " VK_DESCRIPTOR_TYPE_SAMPLER descriptor(s) and a single texture.\n"; 5618 } 5619 else if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) 5620 { 5621 msg << "Single descriptor set. Descriptor set contains " 5622 << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" : 5623 (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? "two" : 5624 (m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) ? "two" : 5625 (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" : 5626 (const char*)DE_NULL) 5627 << " VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER descriptor(s).\n"; 5628 } 5629 else 5630 DE_FATAL("Impossible"); 5631 5632 msg << "Image view type is " << vk::getImageViewTypeName(m_viewType) << "\n"; 5633 5634 if (m_baseMipLevel) 5635 msg << "Image view base mip level = " << m_baseMipLevel << "\n"; 5636 if (m_baseArraySlice) 5637 msg << "Image view base array slice = " << m_baseArraySlice << "\n"; 5638 5639 if (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) 5640 msg << "Sampler mode is LINEAR, with WRAP\n"; 5641 else 5642 msg << "Sampler 0 mode is LINEAR, with WRAP\nSampler 1 mode is NEAREST with CLAMP\n"; 5643 5644 if (m_stageFlags == 0u) 5645 { 5646 msg << "Descriptors are not accessed in any shader stage.\n"; 5647 } 5648 else 5649 { 5650 msg << "Color in each cell is fetched using the descriptor(s):\n"; 5651 5652 for (int resultNdx = 0; resultNdx < 4; ++resultNdx) 5653 { 5654 msg << "Test sample " << resultNdx << ": sample at position " << m_images.getSamplePos(m_viewType, m_baseMipLevel, m_baseArraySlice, resultNdx); 5655 5656 if (m_shaderInterface != SHADER_INPUT_SINGLE_DESCRIPTOR) 5657 { 5658 const int srcResourceNdx = (resultNdx % 2); // ABAB source 5659 5660 if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER) 5661 msg << " using sampler " << srcResourceNdx; 5662 else if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) 5663 msg << " from combined image sampler " << srcResourceNdx; 5664 else 5665 DE_FATAL("Impossible"); 5666 } 5667 msg << "\n"; 5668 } 5669 5670 msg << "Descriptors are accessed in {" 5671 << (((m_stageFlags & vk::VK_SHADER_STAGE_VERTEX_BIT) != 0) ? (" vertex") : ("")) 5672 << (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0) ? (" tess_control") : ("")) 5673 << (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0) ? (" tess_evaluation") : ("")) 5674 << (((m_stageFlags & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0) ? (" geometry") : ("")) 5675 << (((m_stageFlags & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0) ? (" fragment") : ("")) 5676 << " } stages."; 5677 } 5678 5679 m_context.getTestContext().getLog() 5680 << tcu::TestLog::Message 5681 << msg.str() 5682 << tcu::TestLog::EndMessage; 5683 } 5684 5685 vk::VkPipelineLayout ImageSampleRenderInstance::getPipelineLayout (void) const 5686 { 5687 return *m_pipelineLayout; 5688 } 5689 5690 void ImageSampleRenderInstance::writeDrawCmdBuffer (vk::VkCommandBuffer cmd) const 5691 { 5692 if (m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE && m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH) 5693 { 5694 m_vki.cmdBindDescriptorSets(cmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, getPipelineLayout(), 0u, 1u, &m_descriptorSet.get(), 0u, DE_NULL); 5695 } 5696 else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE) 5697 { 5698 m_vki.cmdPushDescriptorSetWithTemplateKHR(cmd, *m_updateTemplate, getPipelineLayout(), 0, (const void*)m_updateRegistry.getRawPointer()); 5699 } 5700 else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH) 5701 { 5702 m_updateBuilder.updateWithPush(m_vki, cmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0); 5703 } 5704 5705 m_vki.cmdDraw(cmd, 6u * 4u, 1u, 0u, 0u); // render four quads (two separate triangles) 5706 } 5707 5708 tcu::TestStatus ImageSampleRenderInstance::verifyResultImage (const tcu::ConstPixelBufferAccess& result) const 5709 { 5710 const tcu::Vec4 green (0.0f, 1.0f, 0.0f, 1.0f); 5711 const tcu::Vec4 yellow (1.0f, 1.0f, 0.0f, 1.0f); 5712 const bool doFetch = (m_stageFlags != 0u); // no active stages? Then don't fetch 5713 const tcu::Vec4 sample0 = (!doFetch) ? (yellow) : (m_images.fetchSampleValue(0)); 5714 const tcu::Vec4 sample1 = (!doFetch) ? (green) : (m_images.fetchSampleValue(1)); 5715 const tcu::Vec4 sample2 = (!doFetch) ? (green) : (m_images.fetchSampleValue(2)); 5716 const tcu::Vec4 sample3 = (!doFetch) ? (yellow) : (m_images.fetchSampleValue(3)); 5717 const tcu::RGBA threshold = tcu::RGBA(8, 8, 8, 8); // source image is high-frequency so the threshold is quite large to tolerate sampling errors 5718 tcu::Surface reference (m_targetSize.x(), m_targetSize.y()); 5719 5720 drawQuadrantReferenceResult(reference.getAccess(), sample0, sample1, sample2, sample3); 5721 5722 if (!bilinearCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", reference.getAccess(), result, threshold, tcu::COMPARE_LOG_RESULT)) 5723 return tcu::TestStatus::fail("Image verification failed"); 5724 else 5725 return tcu::TestStatus::pass("Pass"); 5726 } 5727 5728 class ImageSampleComputeInstance : public vkt::TestInstance 5729 { 5730 public: 5731 ImageSampleComputeInstance (vkt::Context& context, 5732 DescriptorUpdateMethod updateMethod, 5733 vk::VkDescriptorType descriptorType, 5734 ShaderInputInterface shaderInterface, 5735 vk::VkImageViewType viewType, 5736 deUint32 baseMipLevel, 5737 deUint32 baseArraySlice, 5738 bool isImmutableSampler); 5739 5740 private: 5741 vk::Move<vk::VkDescriptorSetLayout> createDescriptorSetLayout (void) const; 5742 vk::Move<vk::VkDescriptorPool> createDescriptorPool (void) const; 5743 vk::Move<vk::VkDescriptorSet> createDescriptorSet (vk::VkDescriptorPool pool, vk::VkDescriptorSetLayout layout); 5744 void writeDescriptorSet (vk::VkDescriptorSet descriptorSet, vk::VkDescriptorSetLayout layout, vk::VkPipelineLayout pipelineLayout = DE_NULL); 5745 void writeImageSamplerDescriptorSet (vk::VkDescriptorSet descriptorSet); 5746 void writeImageSamplerDescriptorSetWithTemplate (vk::VkDescriptorSet descriptorSet, vk::VkDescriptorSetLayout layout, bool withPush = false, vk::VkPipelineLayout pipelineLayout = DE_NULL); 5747 void writeSamplerDescriptorSet (vk::VkDescriptorSet descriptorSet); 5748 void writeSamplerDescriptorSetWithTemplate (vk::VkDescriptorSet descriptorSet, vk::VkDescriptorSetLayout layout, bool withPush = false, vk::VkPipelineLayout pipelineLayout = DE_NULL); 5749 5750 tcu::TestStatus iterate (void); 5751 void logTestPlan (void) const; 5752 tcu::TestStatus testResourceAccess (void); 5753 5754 const DescriptorUpdateMethod m_updateMethod; 5755 const vk::VkDescriptorType m_descriptorType; 5756 const ShaderInputInterface m_shaderInterface; 5757 const vk::VkImageViewType m_viewType; 5758 const deUint32 m_baseMipLevel; 5759 const deUint32 m_baseArraySlice; 5760 const bool m_isImmutableSampler; 5761 vk::Move<vk::VkDescriptorUpdateTemplateKHR> m_updateTemplate; 5762 5763 const vk::DeviceInterface& m_vki; 5764 const vk::VkDevice m_device; 5765 const vk::VkQueue m_queue; 5766 const deUint32 m_queueFamilyIndex; 5767 vk::Allocator& m_allocator; 5768 5769 const ComputeInstanceResultBuffer m_result; 5770 const ImageSampleInstanceImages m_images; 5771 5772 RawUpdateRegistry m_updateRegistry; 5773 vk::DescriptorSetUpdateBuilder m_updateBuilder; 5774 }; 5775 5776 ImageSampleComputeInstance::ImageSampleComputeInstance (Context& context, 5777 DescriptorUpdateMethod updateMethod, 5778 vk::VkDescriptorType descriptorType, 5779 ShaderInputInterface shaderInterface, 5780 vk::VkImageViewType viewType, 5781 deUint32 baseMipLevel, 5782 deUint32 baseArraySlice, 5783 bool isImmutableSampler) 5784 : vkt::TestInstance (context) 5785 , m_updateMethod (updateMethod) 5786 , m_descriptorType (descriptorType) 5787 , m_shaderInterface (shaderInterface) 5788 , m_viewType (viewType) 5789 , m_baseMipLevel (baseMipLevel) 5790 , m_baseArraySlice (baseArraySlice) 5791 , m_isImmutableSampler (isImmutableSampler) 5792 , m_updateTemplate () 5793 , m_vki (context.getDeviceInterface()) 5794 , m_device (context.getDevice()) 5795 , m_queue (context.getUniversalQueue()) 5796 , m_queueFamilyIndex (context.getUniversalQueueFamilyIndex()) 5797 , m_allocator (context.getDefaultAllocator()) 5798 , m_result (m_vki, m_device, m_allocator) 5799 , m_images (m_vki, m_device, m_queueFamilyIndex, m_queue, m_allocator, m_descriptorType, m_shaderInterface, m_viewType, m_baseMipLevel, m_baseArraySlice, isImmutableSampler) 5800 , m_updateRegistry () 5801 , m_updateBuilder () 5802 { 5803 } 5804 5805 vk::Move<vk::VkDescriptorSetLayout> ImageSampleComputeInstance::createDescriptorSetLayout (void) const 5806 { 5807 const vk::VkSampler samplers[2] = 5808 { 5809 m_images.getSamplerA(), 5810 m_images.getSamplerB(), 5811 }; 5812 5813 vk::DescriptorSetLayoutBuilder builder; 5814 vk::VkDescriptorSetLayoutCreateFlags extraFlags = 0; 5815 5816 if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE || 5817 m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH) 5818 { 5819 extraFlags |= vk::VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR; 5820 } 5821 5822 // result buffer 5823 builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT); 5824 5825 // with samplers, separate texture at binding 0 5826 if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER) 5827 builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, vk::VK_SHADER_STAGE_COMPUTE_BIT); 5828 5829 // (combined)samplers follow 5830 switch (m_shaderInterface) 5831 { 5832 case SHADER_INPUT_SINGLE_DESCRIPTOR: 5833 builder.addSingleSamplerBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, (m_images.isImmutable()) ? (&samplers[0]) : (DE_NULL)); 5834 break; 5835 5836 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS: 5837 builder.addSingleSamplerBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, (m_images.isImmutable()) ? (&samplers[0]) : (DE_NULL)); 5838 builder.addSingleSamplerBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT, (m_images.isImmutable()) ? (&samplers[1]) : (DE_NULL)); 5839 break; 5840 5841 case SHADER_INPUT_DESCRIPTOR_ARRAY: 5842 builder.addArraySamplerBinding(m_descriptorType, 2u, vk::VK_SHADER_STAGE_COMPUTE_BIT, (m_images.isImmutable()) ? (samplers) : (DE_NULL)); 5843 break; 5844 5845 default: 5846 DE_FATAL("Impossible"); 5847 }; 5848 5849 return builder.build(m_vki, m_device, extraFlags); 5850 } 5851 5852 vk::Move<vk::VkDescriptorPool> ImageSampleComputeInstance::createDescriptorPool (void) const 5853 { 5854 vk::DescriptorPoolBuilder builder; 5855 5856 builder.addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER); 5857 builder.addType(m_descriptorType, getInterfaceNumResources(m_shaderInterface)); 5858 5859 if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER) 5860 builder.addType(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE); 5861 5862 return builder.build(m_vki, m_device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1); 5863 } 5864 5865 vk::Move<vk::VkDescriptorSet> ImageSampleComputeInstance::createDescriptorSet (vk::VkDescriptorPool pool, vk::VkDescriptorSetLayout layout) 5866 { 5867 const vk::VkDescriptorSetAllocateInfo allocInfo = 5868 { 5869 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, 5870 DE_NULL, 5871 pool, 5872 1u, 5873 &layout 5874 }; 5875 5876 if (m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE && m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH) 5877 { 5878 vk::Move<vk::VkDescriptorSet> descriptorSet = allocateDescriptorSet(m_vki, m_device, &allocInfo); 5879 writeDescriptorSet(*descriptorSet, layout); 5880 5881 return descriptorSet; 5882 } 5883 5884 return vk::Move<vk::VkDescriptorSet>(); 5885 } 5886 5887 void ImageSampleComputeInstance::writeDescriptorSet (vk::VkDescriptorSet descriptorSet, vk::VkDescriptorSetLayout layout, vk::VkPipelineLayout pipelineLayout) 5888 { 5889 if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_TEMPLATE) 5890 { 5891 if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER) 5892 writeSamplerDescriptorSetWithTemplate(descriptorSet, layout); 5893 else if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) 5894 writeImageSamplerDescriptorSetWithTemplate(descriptorSet, layout); 5895 else 5896 DE_FATAL("Impossible"); 5897 } 5898 else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE) 5899 { 5900 if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER) 5901 writeSamplerDescriptorSetWithTemplate(descriptorSet, layout, true, pipelineLayout); 5902 else if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) 5903 writeImageSamplerDescriptorSetWithTemplate(descriptorSet, layout, true, pipelineLayout); 5904 else 5905 DE_FATAL("Impossible"); 5906 } 5907 else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH) 5908 { 5909 if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER) 5910 writeSamplerDescriptorSet(descriptorSet); 5911 else if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) 5912 writeImageSamplerDescriptorSet(descriptorSet); 5913 else 5914 DE_FATAL("Impossible"); 5915 } 5916 else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL) 5917 { 5918 if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER) 5919 writeSamplerDescriptorSet(descriptorSet); 5920 else if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) 5921 writeImageSamplerDescriptorSet(descriptorSet); 5922 else 5923 DE_FATAL("Impossible"); 5924 } 5925 } 5926 5927 void ImageSampleComputeInstance::writeSamplerDescriptorSet (vk::VkDescriptorSet descriptorSet) 5928 { 5929 const vk::VkDescriptorBufferInfo resultInfo = vk::makeDescriptorBufferInfo(m_result.getBuffer(), 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE); 5930 const vk::VkDescriptorImageInfo imageInfo = makeDescriptorImageInfo(m_images.getImageViewA(), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); 5931 const vk::VkDescriptorImageInfo samplersInfos[2] = 5932 { 5933 makeDescriptorImageInfo(m_images.getSamplerA()), 5934 makeDescriptorImageInfo(m_images.getSamplerB()), 5935 }; 5936 5937 // result 5938 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultInfo); 5939 5940 // stand alone texture 5941 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, &imageInfo); 5942 5943 // samplers 5944 if (!m_isImmutableSampler || (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)) 5945 { 5946 switch (m_shaderInterface) 5947 { 5948 case SHADER_INPUT_SINGLE_DESCRIPTOR: 5949 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[0]); 5950 break; 5951 5952 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS: 5953 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[0]); 5954 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(3u), vk::VK_DESCRIPTOR_TYPE_SAMPLER, &samplersInfos[1]); 5955 break; 5956 5957 case SHADER_INPUT_DESCRIPTOR_ARRAY: 5958 m_updateBuilder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), vk::VK_DESCRIPTOR_TYPE_SAMPLER, 2u, samplersInfos); 5959 break; 5960 5961 default: 5962 DE_FATAL("Impossible"); 5963 } 5964 } 5965 5966 if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL) 5967 { 5968 m_updateBuilder.update(m_vki, m_device); 5969 } 5970 } 5971 5972 void ImageSampleComputeInstance::writeSamplerDescriptorSetWithTemplate (vk::VkDescriptorSet descriptorSet, vk::VkDescriptorSetLayout layout, bool withPush, vk::VkPipelineLayout pipelineLayout) 5973 { 5974 std::vector<vk::VkDescriptorUpdateTemplateEntryKHR> updateEntries; 5975 const vk::VkDescriptorBufferInfo resultInfo = vk::makeDescriptorBufferInfo(m_result.getBuffer(), 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE); 5976 const vk::VkDescriptorImageInfo imageInfo = makeDescriptorImageInfo(m_images.getImageViewA(), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); 5977 const vk::VkDescriptorImageInfo samplersInfos[2] = 5978 { 5979 makeDescriptorImageInfo(m_images.getSamplerA()), 5980 makeDescriptorImageInfo(m_images.getSamplerB()), 5981 }; 5982 vk::VkDescriptorUpdateTemplateCreateInfoKHR templateCreateInfo = 5983 { 5984 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR, 5985 DE_NULL, 5986 0, 5987 0, // updateCount 5988 DE_NULL, // pUpdates 5989 withPush ? vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR : vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR, 5990 layout, 5991 vk::VK_PIPELINE_BIND_POINT_COMPUTE, 5992 pipelineLayout, 5993 0 5994 }; 5995 m_updateRegistry.addWriteObject(resultInfo); 5996 m_updateRegistry.addWriteObject(imageInfo); 5997 m_updateRegistry.addWriteObject(samplersInfos[0]); 5998 m_updateRegistry.addWriteObject(samplersInfos[1]); 5999 6000 // result 6001 updateEntries.push_back(createTemplateBinding(0, 0, 1, vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, m_updateRegistry.getWriteObjectOffset(0), 0)); 6002 // stand alone texture 6003 updateEntries.push_back(createTemplateBinding(1, 0, 1, vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, m_updateRegistry.getWriteObjectOffset(1), 0)); 6004 6005 // samplers 6006 if (!m_isImmutableSampler || withPush) 6007 { 6008 switch (m_shaderInterface) 6009 { 6010 case SHADER_INPUT_SINGLE_DESCRIPTOR: 6011 updateEntries.push_back(createTemplateBinding(2, 0, 1, vk::VK_DESCRIPTOR_TYPE_SAMPLER, m_updateRegistry.getWriteObjectOffset(2), 0)); 6012 break; 6013 6014 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS: 6015 updateEntries.push_back(createTemplateBinding(2, 0, 1, vk::VK_DESCRIPTOR_TYPE_SAMPLER, m_updateRegistry.getWriteObjectOffset(2), 0)); 6016 updateEntries.push_back(createTemplateBinding(3, 0, 1, vk::VK_DESCRIPTOR_TYPE_SAMPLER, m_updateRegistry.getWriteObjectOffset(3), 0)); 6017 break; 6018 6019 case SHADER_INPUT_DESCRIPTOR_ARRAY: 6020 updateEntries.push_back(createTemplateBinding(2, 0, 2, vk::VK_DESCRIPTOR_TYPE_SAMPLER, m_updateRegistry.getWriteObjectOffset(2), sizeof(samplersInfos[0]))); 6021 break; 6022 6023 default: 6024 DE_FATAL("Impossible"); 6025 } 6026 } 6027 6028 templateCreateInfo.pDescriptorUpdateEntries = &updateEntries[0]; 6029 templateCreateInfo.descriptorUpdateEntryCount = (deUint32)updateEntries.size(); 6030 6031 m_updateTemplate = vk::createDescriptorUpdateTemplateKHR(m_vki, m_device, &templateCreateInfo); 6032 6033 if (!withPush) 6034 { 6035 m_vki.updateDescriptorSetWithTemplateKHR(m_device, descriptorSet, *m_updateTemplate, m_updateRegistry.getRawPointer()); 6036 } 6037 } 6038 6039 void ImageSampleComputeInstance::writeImageSamplerDescriptorSet (vk::VkDescriptorSet descriptorSet) 6040 { 6041 const vk::VkDescriptorBufferInfo resultInfo = vk::makeDescriptorBufferInfo(m_result.getBuffer(), 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE); 6042 const vk::VkSampler samplers[2] = 6043 { 6044 (m_isImmutableSampler && (m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)) ? (0) : (m_images.getSamplerA()), 6045 (m_isImmutableSampler && (m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH)) ? (0) : (m_images.getSamplerB()), 6046 }; 6047 const vk::VkDescriptorImageInfo imageSamplers[2] = 6048 { 6049 makeDescriptorImageInfo(samplers[0], m_images.getImageViewA(), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL), 6050 makeDescriptorImageInfo(samplers[1], m_images.getImageViewB(), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL), 6051 }; 6052 6053 // result 6054 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultInfo); 6055 6056 // combined image samplers 6057 switch (m_shaderInterface) 6058 { 6059 case SHADER_INPUT_SINGLE_DESCRIPTOR: 6060 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[0]); 6061 break; 6062 6063 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS: 6064 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[0]); 6065 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &imageSamplers[1]); 6066 break; 6067 6068 case SHADER_INPUT_DESCRIPTOR_ARRAY: 6069 m_updateBuilder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2u, imageSamplers); 6070 break; 6071 6072 default: 6073 DE_FATAL("Impossible"); 6074 } 6075 6076 if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL) 6077 { 6078 m_updateBuilder.update(m_vki, m_device); 6079 } 6080 } 6081 6082 void ImageSampleComputeInstance::writeImageSamplerDescriptorSetWithTemplate (vk::VkDescriptorSet descriptorSet, vk::VkDescriptorSetLayout layout, bool withPush, vk::VkPipelineLayout pipelineLayout) 6083 { 6084 std::vector<vk::VkDescriptorUpdateTemplateEntryKHR> updateEntries; 6085 const vk::VkDescriptorBufferInfo resultInfo = vk::makeDescriptorBufferInfo(m_result.getBuffer(), 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE); 6086 const vk::VkSampler samplers[2] = 6087 { 6088 (m_isImmutableSampler && !withPush) ? (0) : (m_images.getSamplerA()), 6089 (m_isImmutableSampler && !withPush) ? (0) : (m_images.getSamplerB()), 6090 }; 6091 const vk::VkDescriptorImageInfo imageSamplers[2] = 6092 { 6093 makeDescriptorImageInfo(samplers[0], m_images.getImageViewA(), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL), 6094 makeDescriptorImageInfo(samplers[1], m_images.getImageViewB(), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL), 6095 }; 6096 vk::VkDescriptorUpdateTemplateCreateInfoKHR templateCreateInfo = 6097 { 6098 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR, 6099 DE_NULL, 6100 0, 6101 0, // updateCount 6102 DE_NULL, // pUpdates 6103 withPush ? vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR : vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR, 6104 layout, 6105 vk::VK_PIPELINE_BIND_POINT_COMPUTE, 6106 pipelineLayout, 6107 0 6108 }; 6109 m_updateRegistry.addWriteObject(resultInfo); 6110 m_updateRegistry.addWriteObject(imageSamplers[0]); 6111 m_updateRegistry.addWriteObject(imageSamplers[1]); 6112 6113 // result 6114 updateEntries.push_back(createTemplateBinding(0, 0, 1, vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, m_updateRegistry.getWriteObjectOffset(0), 0)); 6115 6116 // combined image samplers 6117 switch (m_shaderInterface) 6118 { 6119 case SHADER_INPUT_SINGLE_DESCRIPTOR: 6120 updateEntries.push_back(createTemplateBinding(1, 0, 1, vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, m_updateRegistry.getWriteObjectOffset(1), 0)); 6121 break; 6122 6123 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS: 6124 updateEntries.push_back(createTemplateBinding(1, 0, 1, vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, m_updateRegistry.getWriteObjectOffset(1), 0)); 6125 updateEntries.push_back(createTemplateBinding(2, 0, 1, vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, m_updateRegistry.getWriteObjectOffset(2), 0)); 6126 break; 6127 6128 case SHADER_INPUT_DESCRIPTOR_ARRAY: 6129 updateEntries.push_back(createTemplateBinding(1, 0, 2, vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, m_updateRegistry.getWriteObjectOffset(1), sizeof(imageSamplers[0]))); 6130 break; 6131 6132 default: 6133 DE_FATAL("Impossible"); 6134 } 6135 6136 templateCreateInfo.pDescriptorUpdateEntries = &updateEntries[0]; 6137 templateCreateInfo.descriptorUpdateEntryCount = (deUint32)updateEntries.size(); 6138 6139 m_updateTemplate = vk::createDescriptorUpdateTemplateKHR(m_vki, m_device, &templateCreateInfo); 6140 6141 if (!withPush) 6142 { 6143 m_vki.updateDescriptorSetWithTemplateKHR(m_device, descriptorSet, *m_updateTemplate, m_updateRegistry.getRawPointer()); 6144 } 6145 } 6146 6147 tcu::TestStatus ImageSampleComputeInstance::iterate (void) 6148 { 6149 logTestPlan(); 6150 return testResourceAccess(); 6151 } 6152 6153 void ImageSampleComputeInstance::logTestPlan (void) const 6154 { 6155 std::ostringstream msg; 6156 6157 msg << "Accessing resource in a compute program.\n"; 6158 6159 if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER) 6160 { 6161 msg << "Single descriptor set. Descriptor set contains " 6162 << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" : 6163 (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? "two" : 6164 (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" : 6165 (const char*)DE_NULL) 6166 << " VK_DESCRIPTOR_TYPE_SAMPLER descriptor(s) and a single texture.\n"; 6167 } 6168 else if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) 6169 { 6170 msg << "Single descriptor set. Descriptor set contains " 6171 << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" : 6172 (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? "two" : 6173 (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" : 6174 (const char*)DE_NULL) 6175 << " VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER descriptor(s).\n"; 6176 } 6177 else 6178 DE_FATAL("Impossible"); 6179 6180 msg << "Image view type is " << vk::getImageViewTypeName(m_viewType) << "\n"; 6181 6182 if (m_baseMipLevel) 6183 msg << "Image view base mip level = " << m_baseMipLevel << "\n"; 6184 if (m_baseArraySlice) 6185 msg << "Image view base array slice = " << m_baseArraySlice << "\n"; 6186 6187 if (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) 6188 msg << "Sampler mode is LINEAR, with WRAP\n"; 6189 else 6190 msg << "Sampler 0 mode is LINEAR, with WRAP\nSampler 1 mode is NEAREST with CLAMP\n"; 6191 6192 for (int resultNdx = 0; resultNdx < 4; ++resultNdx) 6193 { 6194 msg << "Test sample " << resultNdx << ": sample at position " << m_images.getSamplePos(m_viewType, m_baseMipLevel, m_baseArraySlice, resultNdx); 6195 6196 if (m_shaderInterface != SHADER_INPUT_SINGLE_DESCRIPTOR) 6197 { 6198 const int srcResourceNdx = (resultNdx % 2); // ABAB source 6199 6200 if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER) 6201 msg << " using sampler " << srcResourceNdx; 6202 else if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) 6203 msg << " from combined image sampler " << srcResourceNdx; 6204 else 6205 DE_FATAL("Impossible"); 6206 } 6207 msg << "\n"; 6208 } 6209 6210 m_context.getTestContext().getLog() 6211 << tcu::TestLog::Message 6212 << msg.str() 6213 << tcu::TestLog::EndMessage; 6214 } 6215 6216 tcu::TestStatus ImageSampleComputeInstance::testResourceAccess (void) 6217 { 6218 const vk::Unique<vk::VkDescriptorSetLayout> descriptorSetLayout (createDescriptorSetLayout()); 6219 const vk::Unique<vk::VkDescriptorPool> descriptorPool (createDescriptorPool()); 6220 const vk::Unique<vk::VkDescriptorSet> descriptorSet (createDescriptorSet(*descriptorPool, *descriptorSetLayout)); 6221 const ComputePipeline pipeline (m_vki, m_device, m_context.getBinaryCollection(), 1, &descriptorSetLayout.get()); 6222 6223 const vk::VkDescriptorSet descriptorSets[] = { *descriptorSet }; 6224 const int numDescriptorSets = (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE || m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH) ? 0 : DE_LENGTH_OF_ARRAY(descriptorSets); 6225 const deUint32* const dynamicOffsets = DE_NULL; 6226 const int numDynamicOffsets = 0; 6227 const vk::VkBufferMemoryBarrier* const preBarriers = DE_NULL; 6228 const int numPreBarriers = 0; 6229 const vk::VkBufferMemoryBarrier* const postBarriers = m_result.getResultReadBarrier(); 6230 const int numPostBarriers = 1; 6231 6232 const ComputeCommand compute (m_vki, 6233 m_device, 6234 pipeline.getPipeline(), 6235 pipeline.getPipelineLayout(), 6236 tcu::UVec3(4, 1, 1), 6237 numDescriptorSets, descriptorSets, 6238 numDynamicOffsets, dynamicOffsets, 6239 numPreBarriers, preBarriers, 6240 numPostBarriers, postBarriers); 6241 6242 tcu::Vec4 results[4]; 6243 bool anyResultSet = false; 6244 bool allResultsOk = true; 6245 6246 if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE) 6247 { 6248 writeDescriptorSet(DE_NULL, *descriptorSetLayout, pipeline.getPipelineLayout()); // descriptor set not applicable 6249 compute.submitAndWait(m_queueFamilyIndex, m_queue, *m_updateTemplate, (void *) m_updateRegistry.getRawPointer()); 6250 } 6251 else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH) 6252 { 6253 writeDescriptorSet(DE_NULL, *descriptorSetLayout, pipeline.getPipelineLayout()); // descriptor set not applicable 6254 compute.submitAndWait(m_queueFamilyIndex, m_queue, m_updateBuilder); 6255 } 6256 else 6257 { 6258 compute.submitAndWait(m_queueFamilyIndex, m_queue); 6259 } 6260 m_result.readResultContentsTo(&results); 6261 6262 // verify 6263 for (int resultNdx = 0; resultNdx < 4; ++resultNdx) 6264 { 6265 const tcu::Vec4 result = results[resultNdx]; 6266 const tcu::Vec4 reference = m_images.fetchSampleValue(resultNdx); 6267 6268 // source image is high-frequency so the threshold is quite large to tolerate sampling errors 6269 const tcu::Vec4 samplingThreshold = tcu::Vec4(8.0f / 255.0f); 6270 6271 if (result != tcu::Vec4(-1.0f)) 6272 anyResultSet = true; 6273 6274 if (tcu::boolAny(tcu::greaterThan(tcu::abs(result - reference), samplingThreshold))) 6275 { 6276 allResultsOk = false; 6277 6278 m_context.getTestContext().getLog() 6279 << tcu::TestLog::Message 6280 << "Test sample " << resultNdx << ":\n" 6281 << "\tSampling at " << m_images.getSamplePos(m_viewType, m_baseMipLevel, m_baseArraySlice, resultNdx) << "\n" 6282 << "\tError expected " << reference << ", got " << result 6283 << tcu::TestLog::EndMessage; 6284 } 6285 } 6286 6287 // read back and verify 6288 if (allResultsOk) 6289 return tcu::TestStatus::pass("Pass"); 6290 else if (anyResultSet) 6291 return tcu::TestStatus::fail("Invalid result values"); 6292 else 6293 { 6294 m_context.getTestContext().getLog() 6295 << tcu::TestLog::Message 6296 << "Result buffer was not written to." 6297 << tcu::TestLog::EndMessage; 6298 return tcu::TestStatus::fail("Result buffer was not written to"); 6299 } 6300 } 6301 6302 class ImageDescriptorCase : public QuadrantRendederCase 6303 { 6304 public: 6305 enum 6306 { 6307 FLAG_BASE_MIP = (1u << 1u), 6308 FLAG_BASE_SLICE = (1u << 2u), 6309 }; 6310 // enum continues where resource flags ends 6311 DE_STATIC_ASSERT((deUint32)FLAG_BASE_MIP == (deUint32)RESOURCE_FLAG_LAST); 6312 6313 ImageDescriptorCase (tcu::TestContext& testCtx, 6314 const char* name, 6315 const char* description, 6316 bool isPrimaryCmdBuf, 6317 DescriptorUpdateMethod updateMethod, 6318 vk::VkDescriptorType descriptorType, 6319 vk::VkShaderStageFlags exitingStages, 6320 vk::VkShaderStageFlags activeStages, 6321 ShaderInputInterface shaderInterface, 6322 vk::VkImageViewType viewType, 6323 deUint32 flags); 6324 6325 private: 6326 std::string genExtensionDeclarations (vk::VkShaderStageFlagBits stage) const; 6327 std::string genResourceDeclarations (vk::VkShaderStageFlagBits stage, int numUsedBindings) const; 6328 std::string genFetchCoordStr (int fetchPosNdx) const; 6329 std::string genSampleCoordStr (int samplePosNdx) const; 6330 std::string genResourceAccessSource (vk::VkShaderStageFlagBits stage) const; 6331 std::string genNoAccessSource (void) const; 6332 6333 vkt::TestInstance* createInstance (vkt::Context& context) const; 6334 6335 private: 6336 const bool m_isPrimaryCmdBuf; 6337 const DescriptorUpdateMethod m_updateMethod; 6338 const vk::VkDescriptorType m_descriptorType; 6339 const ShaderInputInterface m_shaderInterface; 6340 const vk::VkImageViewType m_viewType; 6341 const deUint32 m_baseMipLevel; 6342 const deUint32 m_baseArraySlice; 6343 const bool m_isImmutableSampler; 6344 }; 6345 6346 ImageDescriptorCase::ImageDescriptorCase (tcu::TestContext& testCtx, 6347 const char* name, 6348 const char* description, 6349 bool isPrimaryCmdBuf, 6350 DescriptorUpdateMethod updateMethod, 6351 vk::VkDescriptorType descriptorType, 6352 vk::VkShaderStageFlags exitingStages, 6353 vk::VkShaderStageFlags activeStages, 6354 ShaderInputInterface shaderInterface, 6355 vk::VkImageViewType viewType, 6356 deUint32 flags) 6357 : QuadrantRendederCase (testCtx, name, description, 6358 // \note 1D textures are not supported in ES 6359 (viewType == vk::VK_IMAGE_VIEW_TYPE_1D || viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ? glu::GLSL_VERSION_440 : glu::GLSL_VERSION_310_ES, 6360 exitingStages, activeStages) 6361 , m_isPrimaryCmdBuf (isPrimaryCmdBuf) 6362 , m_updateMethod (updateMethod) 6363 , m_descriptorType (descriptorType) 6364 , m_shaderInterface (shaderInterface) 6365 , m_viewType (viewType) 6366 , m_baseMipLevel (((flags & FLAG_BASE_MIP) != 0) ? (1u) : (0u)) 6367 , m_baseArraySlice (((flags & FLAG_BASE_SLICE) != 0) ? (1u) : (0u)) 6368 , m_isImmutableSampler ((flags & RESOURCE_FLAG_IMMUTABLE_SAMPLER) != 0) 6369 { 6370 } 6371 6372 std::string ImageDescriptorCase::genExtensionDeclarations (vk::VkShaderStageFlagBits stage) const 6373 { 6374 DE_UNREF(stage); 6375 6376 if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) 6377 return "#extension GL_OES_texture_cube_map_array : require\n"; 6378 else 6379 return ""; 6380 } 6381 6382 std::string ImageDescriptorCase::genResourceDeclarations (vk::VkShaderStageFlagBits stage, int numUsedBindings) const 6383 { 6384 DE_UNREF(stage); 6385 6386 // Vulkan-style resources are arrays implicitly, OpenGL-style are not 6387 const std::string dimensionBase = (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D || m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ? ("1D") 6388 : (m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D || m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY) ? ("2D") 6389 : (m_viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? ("3D") 6390 : (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ? ("Cube") 6391 : (DE_NULL); 6392 const std::string dimensionArray = (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D || m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ? ("1DArray") 6393 : (m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D || m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY) ? ("2DArray") 6394 : (m_viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? ("3D") 6395 : (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE || m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ? ("CubeArray") 6396 : (DE_NULL); 6397 const std::string dimension = isImageViewTypeArray(m_viewType) ? dimensionArray : dimensionBase; 6398 6399 if (m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) 6400 DE_ASSERT(m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER); 6401 6402 switch (m_shaderInterface) 6403 { 6404 case SHADER_INPUT_SINGLE_DESCRIPTOR: 6405 { 6406 switch (m_descriptorType) 6407 { 6408 case vk::VK_DESCRIPTOR_TYPE_SAMPLER: 6409 return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ") uniform highp texture" + dimension + " u_separateTexture;\n" 6410 "layout(set = 0, binding = " + de::toString(numUsedBindings+1) + ") uniform highp sampler u_separateSampler;\n"; 6411 case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: 6412 return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ") uniform highp sampler" + dimension + " u_combinedTextureSampler;\n"; 6413 case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: 6414 return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ") uniform highp texture" + dimensionBase + " u_separateTexture;\n"; 6415 case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: 6416 return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ", rgba8) readonly uniform highp image" + dimension + " u_image;\n"; 6417 default: 6418 DE_FATAL("invalid descriptor"); 6419 return ""; 6420 } 6421 } 6422 6423 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS: 6424 case SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS: 6425 switch (m_descriptorType) 6426 { 6427 case vk::VK_DESCRIPTOR_TYPE_SAMPLER: 6428 if (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) 6429 return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ") uniform highp texture" + dimension + " u_separateTexture;\n" 6430 "layout(set = 0, binding = " + de::toString(numUsedBindings+1) + ") uniform highp sampler u_separateSamplerA;\n" 6431 "layout(set = 0, binding = " + de::toString(numUsedBindings+2) + ") uniform highp sampler u_separateSamplerB;\n"; 6432 else 6433 return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ") uniform highp sampler u_separateSamplerA;\n" 6434 "layout(set = 0, binding = " + de::toString(numUsedBindings+1) + ") uniform highp texture" + dimension + " u_separateTexture;\n" 6435 "layout(set = 0, binding = " + de::toString(numUsedBindings+2) + ") uniform highp sampler u_separateSamplerB;\n"; 6436 case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: 6437 return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ") uniform highp sampler" + dimension + " u_combinedTextureSamplerA;\n" 6438 "layout(set = 0, binding = " + de::toString(numUsedBindings+1) + ") uniform highp sampler" + dimension + " u_combinedTextureSamplerB;\n"; 6439 case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: 6440 return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ") uniform highp texture" + dimensionBase + " u_separateTextureA;\n" 6441 "layout(set = 0, binding = " + de::toString(numUsedBindings+1) + ") uniform highp texture" + dimensionBase + " u_separateTextureB;\n"; 6442 case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: 6443 return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ", rgba8) readonly uniform highp image" + dimension + " u_imageA;\n" 6444 "layout(set = 0, binding = " + de::toString(numUsedBindings+1) + ", rgba8) readonly uniform highp image" + dimension + " u_imageB;\n"; 6445 default: 6446 DE_FATAL("invalid descriptor"); 6447 return ""; 6448 } 6449 6450 case SHADER_INPUT_DESCRIPTOR_ARRAY: 6451 switch (m_descriptorType) 6452 { 6453 case vk::VK_DESCRIPTOR_TYPE_SAMPLER: 6454 return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ") uniform highp texture" + dimension + " u_separateTexture;\n" 6455 "layout(set = 0, binding = " + de::toString(numUsedBindings+1) + ") uniform highp sampler u_separateSampler[2];\n"; 6456 case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: 6457 return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ") uniform highp sampler" + dimension + " u_combinedTextureSampler[2];\n"; 6458 case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: 6459 return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ") uniform highp texture" + dimensionBase + " u_separateTexture[2];\n"; 6460 case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: 6461 return "layout(set = 0, binding = " + de::toString(numUsedBindings) + ", rgba8) readonly uniform highp image" + dimension + " u_image[2];\n"; 6462 default: 6463 DE_FATAL("invalid descriptor"); 6464 return ""; 6465 } 6466 6467 default: 6468 DE_FATAL("Impossible"); 6469 return ""; 6470 } 6471 } 6472 6473 std::string ImageDescriptorCase::genFetchCoordStr (int fetchPosNdx) const 6474 { 6475 DE_ASSERT(m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE || m_descriptorType == vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE); 6476 const tcu::IVec3 fetchPos = ImageFetchInstanceImages::getFetchPos(m_viewType, m_baseMipLevel, m_baseArraySlice, fetchPosNdx); 6477 6478 if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D) 6479 { 6480 return de::toString(fetchPos.x()); 6481 } 6482 else if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY || m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D) 6483 { 6484 std::ostringstream buf; 6485 buf << "ivec2(" << fetchPos.x() << ", " << fetchPos.y() << ")"; 6486 return buf.str(); 6487 } 6488 else 6489 { 6490 std::ostringstream buf; 6491 buf << "ivec3(" << fetchPos.x() << ", " << fetchPos.y() << ", " << fetchPos.z() << ")"; 6492 return buf.str(); 6493 } 6494 } 6495 6496 std::string ImageDescriptorCase::genSampleCoordStr (int samplePosNdx) const 6497 { 6498 DE_ASSERT(m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER || m_descriptorType == vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER); 6499 const tcu::Vec4 fetchPos = ImageSampleInstanceImages::getSamplePos(m_viewType, m_baseMipLevel, m_baseArraySlice, samplePosNdx); 6500 6501 if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D) 6502 { 6503 std::ostringstream buf; 6504 buf << "float(" << fetchPos.x() << ")"; 6505 return buf.str(); 6506 } 6507 else if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY || m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D) 6508 { 6509 std::ostringstream buf; 6510 buf << "vec2(float(" << fetchPos.x() << "), float(" << fetchPos.y() << "))"; 6511 return buf.str(); 6512 } 6513 else if (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) 6514 { 6515 std::ostringstream buf; 6516 buf << "vec4(float(" << fetchPos.x() << "), float(" << fetchPos.y() << "), float(" << fetchPos.z() << "), float(" << fetchPos.w() << "))"; 6517 return buf.str(); 6518 } 6519 else 6520 { 6521 std::ostringstream buf; 6522 buf << "vec3(float(" << fetchPos.x() << "), float(" << fetchPos.y() << "), float(" << fetchPos.z() << "))"; 6523 return buf.str(); 6524 } 6525 } 6526 6527 std::string ImageDescriptorCase::genResourceAccessSource (vk::VkShaderStageFlagBits stage) const 6528 { 6529 DE_UNREF(stage); 6530 6531 const char* const dimension = (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D) ? ("1D") 6532 : (m_viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY) ? ("1DArray") 6533 : (m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D) ? ("2D") 6534 : (m_viewType == vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY) ? ("2DArray") 6535 : (m_viewType == vk::VK_IMAGE_VIEW_TYPE_3D) ? ("3D") 6536 : (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE) ? ("Cube") 6537 : (m_viewType == vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) ? ("CubeArray") 6538 : (DE_NULL); 6539 const char* const accessPostfixA = (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? ("") 6540 : (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? ("A") 6541 : (m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) ? ("A") 6542 : (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? ("[0]") 6543 : (DE_NULL); 6544 const char* const accessPostfixB = (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? ("") 6545 : (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? ("B") 6546 : (m_shaderInterface == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) ? ("B") 6547 : (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? ("[1]") 6548 : (DE_NULL); 6549 6550 switch (m_descriptorType) 6551 { 6552 case vk::VK_DESCRIPTOR_TYPE_SAMPLER: 6553 case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: 6554 { 6555 const std::string coodStr[4] = 6556 { 6557 genSampleCoordStr(0), 6558 genSampleCoordStr(1), 6559 genSampleCoordStr(2), 6560 genSampleCoordStr(3), 6561 }; 6562 std::ostringstream buf; 6563 6564 if (m_descriptorType == vk::VK_DESCRIPTOR_TYPE_SAMPLER) 6565 { 6566 buf << " if (quadrant_id == 0)\n" 6567 << " result_color = textureLod(sampler" << dimension << "(u_separateTexture, u_separateSampler" << accessPostfixA << "), " << coodStr[0] << ", 0.0);\n" 6568 << " else if (quadrant_id == 1)\n" 6569 << " result_color = textureLod(sampler" << dimension << "(u_separateTexture, u_separateSampler" << accessPostfixB << "), " << coodStr[1] << ", 0.0);\n" 6570 << " else if (quadrant_id == 2)\n" 6571 << " result_color = textureLod(sampler" << dimension << "(u_separateTexture, u_separateSampler" << accessPostfixA << "), " << coodStr[2] << ", 0.0);\n" 6572 << " else\n" 6573 << " result_color = textureLod(sampler" << dimension << "(u_separateTexture, u_separateSampler" << accessPostfixB << "), " << coodStr[3] << ", 0.0);\n"; 6574 } 6575 else 6576 { 6577 buf << " if (quadrant_id == 0)\n" 6578 << " result_color = textureLod(u_combinedTextureSampler" << accessPostfixA << ", " << coodStr[0] << ", 0.0);\n" 6579 << " else if (quadrant_id == 1)\n" 6580 << " result_color = textureLod(u_combinedTextureSampler" << accessPostfixB << ", " << coodStr[1] << ", 0.0);\n" 6581 << " else if (quadrant_id == 2)\n" 6582 << " result_color = textureLod(u_combinedTextureSampler" << accessPostfixA << ", " << coodStr[2] << ", 0.0);\n" 6583 << " else\n" 6584 << " result_color = textureLod(u_combinedTextureSampler" << accessPostfixB << ", " << coodStr[3] << ", 0.0);\n"; 6585 } 6586 6587 return buf.str(); 6588 } 6589 6590 case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: 6591 { 6592 const std::string coodStr[4] = 6593 { 6594 genFetchCoordStr(0), 6595 genFetchCoordStr(1), 6596 genFetchCoordStr(2), 6597 genFetchCoordStr(3), 6598 }; 6599 std::ostringstream buf; 6600 6601 buf << " if (quadrant_id == 0)\n" 6602 << " result_color = imageLoad(u_image" << accessPostfixA << ", " << coodStr[0] << ");\n" 6603 << " else if (quadrant_id == 1)\n" 6604 << " result_color = imageLoad(u_image" << accessPostfixB << ", " << coodStr[1] << ");\n" 6605 << " else if (quadrant_id == 2)\n" 6606 << " result_color = imageLoad(u_image" << accessPostfixA << ", " << coodStr[2] << ");\n" 6607 << " else\n" 6608 << " result_color = imageLoad(u_image" << accessPostfixB << ", " << coodStr[3] << ");\n"; 6609 6610 return buf.str(); 6611 } 6612 6613 default: 6614 DE_FATAL("invalid descriptor"); 6615 return ""; 6616 } 6617 } 6618 6619 std::string ImageDescriptorCase::genNoAccessSource (void) const 6620 { 6621 return " if (quadrant_id == 1 || quadrant_id == 2)\n" 6622 " result_color = vec4(0.0, 1.0, 0.0, 1.0);\n" 6623 " else\n" 6624 " result_color = vec4(1.0, 1.0, 0.0, 1.0);\n"; 6625 } 6626 6627 vkt::TestInstance* ImageDescriptorCase::createInstance (vkt::Context& context) const 6628 { 6629 verifyDriverSupport(context.getDeviceFeatures(), context.getDeviceExtensions(), m_updateMethod, m_descriptorType, m_activeStages); 6630 6631 switch (m_descriptorType) 6632 { 6633 case vk::VK_DESCRIPTOR_TYPE_SAMPLER: 6634 case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: 6635 if (m_exitingStages == vk::VK_SHADER_STAGE_COMPUTE_BIT) 6636 { 6637 DE_ASSERT(m_isPrimaryCmdBuf); 6638 return new ImageSampleComputeInstance(context, m_updateMethod, m_descriptorType, m_shaderInterface, m_viewType, m_baseMipLevel, m_baseArraySlice, m_isImmutableSampler); 6639 } 6640 else 6641 return new ImageSampleRenderInstance(context, m_updateMethod, m_isPrimaryCmdBuf, m_descriptorType, m_activeStages, m_shaderInterface, m_viewType, m_baseMipLevel, m_baseArraySlice, m_isImmutableSampler); 6642 6643 case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: 6644 case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: 6645 if (m_exitingStages == vk::VK_SHADER_STAGE_COMPUTE_BIT) 6646 { 6647 DE_ASSERT(m_isPrimaryCmdBuf); 6648 return new ImageFetchComputeInstance(context, m_updateMethod, m_descriptorType, m_shaderInterface, m_viewType, m_baseMipLevel, m_baseArraySlice); 6649 } 6650 else 6651 return new ImageFetchRenderInstance(context, m_updateMethod, m_isPrimaryCmdBuf, m_descriptorType, m_activeStages, m_shaderInterface, m_viewType, m_baseMipLevel, m_baseArraySlice); 6652 6653 default: 6654 DE_FATAL("Impossible"); 6655 return DE_NULL; 6656 } 6657 } 6658 6659 class TexelBufferInstanceBuffers 6660 { 6661 public: 6662 TexelBufferInstanceBuffers (const vk::DeviceInterface& vki, 6663 vk::VkDevice device, 6664 vk::Allocator& allocator, 6665 vk::VkDescriptorType descriptorType, 6666 int numTexelBuffers, 6667 bool hasViewOffset); 6668 6669 private: 6670 static vk::Move<vk::VkBuffer> createBuffer (const vk::DeviceInterface& vki, 6671 vk::VkDevice device, 6672 vk::Allocator& allocator, 6673 vk::VkDescriptorType descriptorType, 6674 de::MovePtr<vk::Allocation> *outAllocation); 6675 6676 static vk::Move<vk::VkBufferView> createBufferView (const vk::DeviceInterface& vki, 6677 vk::VkDevice device, 6678 const tcu::TextureFormat& textureFormat, 6679 deUint32 offset, 6680 vk::VkBuffer buffer); 6681 6682 static vk::VkBufferMemoryBarrier createBarrier (vk::VkDescriptorType descriptorType, vk::VkBuffer buffer); 6683 6684 void populateSourceBuffer (const tcu::PixelBufferAccess& access); 6685 void uploadData (const vk::DeviceInterface& vki, vk::VkDevice device, const vk::Allocation& memory, const de::ArrayBuffer<deUint8>& data); 6686 6687 public: 6688 static int getFetchPos (int fetchPosNdx); 6689 tcu::Vec4 fetchTexelValue (int fetchPosNdx) const; 6690 6691 inline int getNumTexelBuffers (void) const { return m_numTexelBuffers; } 6692 const tcu::TextureFormat& getTextureFormat (void) const { return m_imageFormat; } 6693 inline vk::VkBufferView getBufferViewA (void) const { return *m_bufferViewA; } 6694 inline vk::VkBufferView getBufferViewB (void) const { return *m_bufferViewB; } 6695 inline const vk::VkBufferMemoryBarrier* getBufferInitBarriers (void) const { return m_bufferBarriers; } 6696 6697 private: 6698 enum 6699 { 6700 BUFFER_SIZE = 512, 6701 VIEW_OFFSET_VALUE = 256, 6702 VIEW_DATA_SIZE = 256, //!< size in bytes 6703 VIEW_WIDTH = 64, //!< size in pixels 6704 }; 6705 enum 6706 { 6707 // some arbitrary points 6708 SAMPLE_POINT_0 = 6, 6709 SAMPLE_POINT_1 = 51, 6710 SAMPLE_POINT_2 = 42, 6711 SAMPLE_POINT_3 = 25, 6712 }; 6713 6714 const deUint32 m_numTexelBuffers; 6715 const tcu::TextureFormat m_imageFormat; 6716 const deUint32 m_viewOffset; 6717 6718 de::ArrayBuffer<deUint8> m_sourceBufferA; 6719 de::ArrayBuffer<deUint8> m_sourceBufferB; 6720 const tcu::ConstPixelBufferAccess m_sourceViewA; 6721 const tcu::ConstPixelBufferAccess m_sourceViewB; 6722 6723 de::MovePtr<vk::Allocation> m_bufferMemoryA; 6724 de::MovePtr<vk::Allocation> m_bufferMemoryB; 6725 const vk::Unique<vk::VkBuffer> m_bufferA; 6726 const vk::Unique<vk::VkBuffer> m_bufferB; 6727 const vk::Unique<vk::VkBufferView> m_bufferViewA; 6728 const vk::Unique<vk::VkBufferView> m_bufferViewB; 6729 vk::VkBufferMemoryBarrier m_bufferBarriers[2]; 6730 }; 6731 6732 TexelBufferInstanceBuffers::TexelBufferInstanceBuffers (const vk::DeviceInterface& vki, 6733 vk::VkDevice device, 6734 vk::Allocator& allocator, 6735 vk::VkDescriptorType descriptorType, 6736 int numTexelBuffers, 6737 bool hasViewOffset) 6738 : m_numTexelBuffers (numTexelBuffers) 6739 , m_imageFormat (tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8) 6740 , m_viewOffset ((hasViewOffset) ? ((deUint32)VIEW_OFFSET_VALUE) : (0u)) 6741 , m_sourceBufferA (BUFFER_SIZE) 6742 , m_sourceBufferB ((numTexelBuffers == 1) 6743 ? (0u) 6744 : ((size_t)BUFFER_SIZE)) 6745 , m_sourceViewA (m_imageFormat, tcu::IVec3(VIEW_WIDTH, 1, 1), m_sourceBufferA.getElementPtr(m_viewOffset)) 6746 , m_sourceViewB (m_imageFormat, tcu::IVec3(VIEW_WIDTH, 1, 1), m_sourceBufferB.getElementPtr(m_viewOffset)) 6747 , m_bufferMemoryA (DE_NULL) 6748 , m_bufferMemoryB (DE_NULL) 6749 , m_bufferA (createBuffer(vki, device, allocator, descriptorType, &m_bufferMemoryA)) 6750 , m_bufferB ((numTexelBuffers == 1) 6751 ? vk::Move<vk::VkBuffer>() 6752 : createBuffer(vki, device, allocator, descriptorType, &m_bufferMemoryB)) 6753 , m_bufferViewA (createBufferView(vki, device, m_imageFormat, m_viewOffset, *m_bufferA)) 6754 , m_bufferViewB ((numTexelBuffers == 1) 6755 ? vk::Move<vk::VkBufferView>() 6756 : createBufferView(vki, device, m_imageFormat, m_viewOffset, *m_bufferB)) 6757 { 6758 DE_ASSERT(numTexelBuffers == 1 || numTexelBuffers == 2); 6759 DE_ASSERT(VIEW_WIDTH * m_imageFormat.getPixelSize() == VIEW_DATA_SIZE); 6760 DE_ASSERT(BUFFER_SIZE % m_imageFormat.getPixelSize() == 0); 6761 6762 // specify and upload 6763 6764 populateSourceBuffer(tcu::PixelBufferAccess(m_imageFormat, tcu::IVec3(BUFFER_SIZE / m_imageFormat.getPixelSize(), 1, 1), m_sourceBufferA.getPtr())); 6765 uploadData(vki, device, *m_bufferMemoryA, m_sourceBufferA); 6766 6767 if (numTexelBuffers == 2) 6768 { 6769 populateSourceBuffer(tcu::PixelBufferAccess(m_imageFormat, tcu::IVec3(BUFFER_SIZE / m_imageFormat.getPixelSize(), 1, 1), m_sourceBufferB.getPtr())); 6770 uploadData(vki, device, *m_bufferMemoryB, m_sourceBufferB); 6771 } 6772 6773 m_bufferBarriers[0] = createBarrier(descriptorType, *m_bufferA); 6774 m_bufferBarriers[1] = createBarrier(descriptorType, *m_bufferB); 6775 } 6776 6777 vk::Move<vk::VkBuffer> TexelBufferInstanceBuffers::createBuffer (const vk::DeviceInterface& vki, 6778 vk::VkDevice device, 6779 vk::Allocator& allocator, 6780 vk::VkDescriptorType descriptorType, 6781 de::MovePtr<vk::Allocation> *outAllocation) 6782 { 6783 const vk::VkBufferUsageFlags usage = (isUniformDescriptorType(descriptorType)) ? (vk::VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT) : (vk::VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT); 6784 const vk::VkBufferCreateInfo createInfo = 6785 { 6786 vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, 6787 DE_NULL, 6788 0u, // flags 6789 (vk::VkDeviceSize)BUFFER_SIZE, // size 6790 usage, // usage 6791 vk::VK_SHARING_MODE_EXCLUSIVE, // sharingMode 6792 0u, // queueFamilyCount 6793 DE_NULL, // pQueueFamilyIndices 6794 }; 6795 vk::Move<vk::VkBuffer> buffer (vk::createBuffer(vki, device, &createInfo)); 6796 de::MovePtr<vk::Allocation> allocation (allocateAndBindObjectMemory(vki, device, allocator, *buffer, vk::MemoryRequirement::HostVisible)); 6797 6798 *outAllocation = allocation; 6799 return buffer; 6800 } 6801 6802 vk::Move<vk::VkBufferView> TexelBufferInstanceBuffers::createBufferView (const vk::DeviceInterface& vki, 6803 vk::VkDevice device, 6804 const tcu::TextureFormat& textureFormat, 6805 deUint32 offset, 6806 vk::VkBuffer buffer) 6807 { 6808 const vk::VkBufferViewCreateInfo createInfo = 6809 { 6810 vk::VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO, 6811 DE_NULL, 6812 (vk::VkBufferViewCreateFlags)0, 6813 buffer, // buffer 6814 vk::mapTextureFormat(textureFormat), // format 6815 (vk::VkDeviceSize)offset, // offset 6816 (vk::VkDeviceSize)VIEW_DATA_SIZE // range 6817 }; 6818 return vk::createBufferView(vki, device, &createInfo); 6819 } 6820 6821 vk::VkBufferMemoryBarrier TexelBufferInstanceBuffers::createBarrier (vk::VkDescriptorType descriptorType, vk::VkBuffer buffer) 6822 { 6823 const vk::VkAccessFlags inputBit = (isUniformDescriptorType(descriptorType)) ? (vk::VK_ACCESS_UNIFORM_READ_BIT) : (vk::VK_ACCESS_SHADER_READ_BIT); 6824 const vk::VkBufferMemoryBarrier barrier = 6825 { 6826 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 6827 DE_NULL, 6828 vk::VK_ACCESS_HOST_WRITE_BIT, // outputMask 6829 inputBit, // inputMask 6830 VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex 6831 VK_QUEUE_FAMILY_IGNORED, // destQueueFamilyIndex 6832 buffer , // buffer 6833 0u, // offset 6834 (vk::VkDeviceSize)BUFFER_SIZE // size 6835 }; 6836 return barrier; 6837 } 6838 6839 void TexelBufferInstanceBuffers::populateSourceBuffer (const tcu::PixelBufferAccess& access) 6840 { 6841 DE_ASSERT(access.getHeight() == 1); 6842 DE_ASSERT(access.getDepth() == 1); 6843 6844 const deInt32 width = access.getWidth(); 6845 6846 for (int x = 0; x < width; ++x) 6847 { 6848 const int red = 255 * x / width; //!< gradient from 0 -> max (detects large offset errors) 6849 const int green = ((x % 2 == 0) ? (127) : (0)) + ((x % 4 < 3) ? (128) : (0)); //!< 3-level M pattern (detects small offset errors) 6850 const int blue = 16 * (x % 16); //!< 16-long triangle wave 6851 6852 DE_ASSERT(de::inRange(red, 0, 255)); 6853 DE_ASSERT(de::inRange(green, 0, 255)); 6854 DE_ASSERT(de::inRange(blue, 0, 255)); 6855 6856 access.setPixel(tcu::IVec4(red, green, blue, 255), x, 0, 0); 6857 } 6858 } 6859 6860 void TexelBufferInstanceBuffers::uploadData (const vk::DeviceInterface& vki, vk::VkDevice device, const vk::Allocation& memory, const de::ArrayBuffer<deUint8>& data) 6861 { 6862 deMemcpy(memory.getHostPtr(), data.getPtr(), data.size()); 6863 flushMappedMemoryRange(vki, device, memory.getMemory(), memory.getOffset(), data.size()); 6864 } 6865 6866 int TexelBufferInstanceBuffers::getFetchPos (int fetchPosNdx) 6867 { 6868 static const int fetchPositions[4] = 6869 { 6870 SAMPLE_POINT_0, 6871 SAMPLE_POINT_1, 6872 SAMPLE_POINT_2, 6873 SAMPLE_POINT_3, 6874 }; 6875 return de::getSizedArrayElement<4>(fetchPositions, fetchPosNdx); 6876 } 6877 6878 tcu::Vec4 TexelBufferInstanceBuffers::fetchTexelValue (int fetchPosNdx) const 6879 { 6880 // source order is ABAB 6881 const tcu::ConstPixelBufferAccess& texelSrcA = m_sourceViewA; 6882 const tcu::ConstPixelBufferAccess& texelSrcB = (m_numTexelBuffers == 1) ? (m_sourceViewA) : (m_sourceViewB); 6883 const tcu::ConstPixelBufferAccess& texelSrc = ((fetchPosNdx % 2) == 0) ? (texelSrcA) : (texelSrcB); 6884 6885 return texelSrc.getPixel(getFetchPos(fetchPosNdx), 0, 0); 6886 } 6887 6888 class TexelBufferRenderInstance : public SingleCmdRenderInstance 6889 { 6890 public: 6891 TexelBufferRenderInstance (vkt::Context& context, 6892 DescriptorUpdateMethod updateMethod, 6893 bool isPrimaryCmdBuf, 6894 vk::VkDescriptorType descriptorType, 6895 vk::VkShaderStageFlags stageFlags, 6896 ShaderInputInterface shaderInterface, 6897 bool nonzeroViewOffset); 6898 6899 private: 6900 static vk::Move<vk::VkDescriptorSetLayout> createDescriptorSetLayout (const vk::DeviceInterface& vki, 6901 vk::VkDevice device, 6902 vk::VkDescriptorType descriptorType, 6903 ShaderInputInterface shaderInterface, 6904 vk::VkShaderStageFlags stageFlags, 6905 DescriptorUpdateMethod updateMethod); 6906 6907 static vk::Move<vk::VkPipelineLayout> createPipelineLayout (const vk::DeviceInterface& vki, 6908 vk::VkDevice device, 6909 vk::VkDescriptorSetLayout descriptorSetLayout); 6910 6911 static vk::Move<vk::VkDescriptorPool> createDescriptorPool (const vk::DeviceInterface& vki, 6912 vk::VkDevice device, 6913 vk::VkDescriptorType descriptorType, 6914 ShaderInputInterface shaderInterface); 6915 6916 static vk::Move<vk::VkDescriptorSet> createDescriptorSet (const vk::DeviceInterface& vki, 6917 DescriptorUpdateMethod updateMethod, 6918 vk::VkDevice device, 6919 vk::VkDescriptorType descriptorType, 6920 ShaderInputInterface shaderInterface, 6921 vk::VkDescriptorSetLayout layout, 6922 vk::VkDescriptorPool pool, 6923 vk::VkBufferView viewA, 6924 vk::VkBufferView viewB, 6925 vk::DescriptorSetUpdateBuilder& updateBuilder, 6926 vk::Move<vk::VkDescriptorUpdateTemplateKHR>& updateTemplate, 6927 RawUpdateRegistry& updateRegistry, 6928 vk::VkPipelineLayout pipelineLayout = DE_NULL); 6929 6930 static void writeDescriptorSet (const vk::DeviceInterface& vki, 6931 vk::VkDevice device, 6932 vk::VkDescriptorType descriptorType, 6933 ShaderInputInterface shaderInterface, 6934 vk::VkDescriptorSetLayout layout, 6935 vk::VkDescriptorPool pool, 6936 vk::VkBufferView viewA, 6937 vk::VkBufferView viewB, 6938 vk::VkDescriptorSet descriptorSet, 6939 vk::DescriptorSetUpdateBuilder& updateBuilder, 6940 DescriptorUpdateMethod updateMethod = DESCRIPTOR_UPDATE_METHOD_NORMAL); 6941 6942 static void writeDescriptorSetWithTemplate (const vk::DeviceInterface& vki, 6943 vk::VkDevice device, 6944 vk::VkDescriptorType descriptorType, 6945 ShaderInputInterface shaderInterface, 6946 vk::VkDescriptorSetLayout layout, 6947 vk::VkDescriptorPool pool, 6948 vk::VkBufferView viewA, 6949 vk::VkBufferView viewB, 6950 vk::VkDescriptorSet descriptorSet, 6951 vk::Move<vk::VkDescriptorUpdateTemplateKHR>& updateTemplate, 6952 RawUpdateRegistry& updateRegistry, 6953 bool withPush = false, 6954 vk::VkPipelineLayout pipelineLayout = 0); 6955 6956 void logTestPlan (void) const; 6957 vk::VkPipelineLayout getPipelineLayout (void) const; 6958 void writeDrawCmdBuffer (vk::VkCommandBuffer cmd) const; 6959 tcu::TestStatus verifyResultImage (const tcu::ConstPixelBufferAccess& result) const; 6960 6961 enum 6962 { 6963 RENDER_SIZE = 128, 6964 }; 6965 6966 const DescriptorUpdateMethod m_updateMethod; 6967 const vk::VkDescriptorType m_descriptorType; 6968 const vk::VkShaderStageFlags m_stageFlags; 6969 const ShaderInputInterface m_shaderInterface; 6970 const bool m_nonzeroViewOffset; 6971 6972 vk::Move<vk::VkDescriptorUpdateTemplateKHR> m_updateTemplate; 6973 RawUpdateRegistry m_updateRegistry; 6974 vk::DescriptorSetUpdateBuilder m_updateBuilder; 6975 const vk::Unique<vk::VkDescriptorSetLayout> m_descriptorSetLayout; 6976 const vk::Unique<vk::VkPipelineLayout> m_pipelineLayout; 6977 const TexelBufferInstanceBuffers m_texelBuffers; 6978 const vk::Unique<vk::VkDescriptorPool> m_descriptorPool; 6979 const vk::Unique<vk::VkDescriptorSet> m_descriptorSet; 6980 }; 6981 6982 TexelBufferRenderInstance::TexelBufferRenderInstance (vkt::Context& context, 6983 DescriptorUpdateMethod updateMethod, 6984 bool isPrimaryCmdBuf, 6985 vk::VkDescriptorType descriptorType, 6986 vk::VkShaderStageFlags stageFlags, 6987 ShaderInputInterface shaderInterface, 6988 bool nonzeroViewOffset) 6989 : SingleCmdRenderInstance (context, isPrimaryCmdBuf, tcu::UVec2(RENDER_SIZE, RENDER_SIZE)) 6990 , m_updateMethod (updateMethod) 6991 , m_descriptorType (descriptorType) 6992 , m_stageFlags (stageFlags) 6993 , m_shaderInterface (shaderInterface) 6994 , m_nonzeroViewOffset (nonzeroViewOffset) 6995 , m_updateTemplate () 6996 , m_updateRegistry () 6997 , m_updateBuilder () 6998 , m_descriptorSetLayout (createDescriptorSetLayout(m_vki, m_device, m_descriptorType, m_shaderInterface, m_stageFlags, m_updateMethod)) 6999 , m_pipelineLayout (createPipelineLayout(m_vki, m_device, *m_descriptorSetLayout)) 7000 , m_texelBuffers (m_vki, m_device, m_allocator, m_descriptorType, getInterfaceNumResources(m_shaderInterface), m_nonzeroViewOffset) 7001 , m_descriptorPool (createDescriptorPool(m_vki, m_device, m_descriptorType, m_shaderInterface)) 7002 , m_descriptorSet (createDescriptorSet(m_vki, m_updateMethod, m_device, m_descriptorType, m_shaderInterface, *m_descriptorSetLayout, *m_descriptorPool, m_texelBuffers.getBufferViewA(), m_texelBuffers.getBufferViewB(), m_updateBuilder, m_updateTemplate, m_updateRegistry, *m_pipelineLayout)) 7003 { 7004 } 7005 7006 vk::Move<vk::VkDescriptorSetLayout> TexelBufferRenderInstance::createDescriptorSetLayout (const vk::DeviceInterface& vki, 7007 vk::VkDevice device, 7008 vk::VkDescriptorType descriptorType, 7009 ShaderInputInterface shaderInterface, 7010 vk::VkShaderStageFlags stageFlags, 7011 DescriptorUpdateMethod updateMethod) 7012 { 7013 vk::DescriptorSetLayoutBuilder builder; 7014 vk::VkDescriptorSetLayoutCreateFlags extraFlags = 0; 7015 7016 if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE || 7017 updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH) 7018 { 7019 extraFlags |= vk::VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR; 7020 } 7021 7022 switch (shaderInterface) 7023 { 7024 case SHADER_INPUT_SINGLE_DESCRIPTOR: 7025 builder.addSingleBinding(descriptorType, stageFlags); 7026 break; 7027 7028 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS: 7029 builder.addSingleBinding(descriptorType, stageFlags); 7030 builder.addSingleBinding(descriptorType, stageFlags); 7031 break; 7032 7033 case SHADER_INPUT_DESCRIPTOR_ARRAY: 7034 builder.addArrayBinding(descriptorType, 2u, stageFlags); 7035 break; 7036 7037 default: 7038 DE_FATAL("Impossible"); 7039 } 7040 7041 return builder.build(vki, device, extraFlags); 7042 } 7043 7044 vk::Move<vk::VkPipelineLayout> TexelBufferRenderInstance::createPipelineLayout (const vk::DeviceInterface& vki, 7045 vk::VkDevice device, 7046 vk::VkDescriptorSetLayout descriptorSetLayout) 7047 { 7048 const vk::VkPipelineLayoutCreateInfo createInfo = 7049 { 7050 vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, 7051 DE_NULL, 7052 (vk::VkPipelineLayoutCreateFlags)0, 7053 1, // descriptorSetCount 7054 &descriptorSetLayout, // pSetLayouts 7055 0u, // pushConstantRangeCount 7056 DE_NULL, // pPushConstantRanges 7057 }; 7058 return vk::createPipelineLayout(vki, device, &createInfo); 7059 } 7060 7061 vk::Move<vk::VkDescriptorPool> TexelBufferRenderInstance::createDescriptorPool (const vk::DeviceInterface& vki, 7062 vk::VkDevice device, 7063 vk::VkDescriptorType descriptorType, 7064 ShaderInputInterface shaderInterface) 7065 { 7066 return vk::DescriptorPoolBuilder() 7067 .addType(descriptorType, getInterfaceNumResources(shaderInterface)) 7068 .build(vki, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1); 7069 } 7070 7071 vk::Move<vk::VkDescriptorSet> TexelBufferRenderInstance::createDescriptorSet (const vk::DeviceInterface& vki, 7072 DescriptorUpdateMethod updateMethod, 7073 vk::VkDevice device, 7074 vk::VkDescriptorType descriptorType, 7075 ShaderInputInterface shaderInterface, 7076 vk::VkDescriptorSetLayout layout, 7077 vk::VkDescriptorPool pool, 7078 vk::VkBufferView viewA, 7079 vk::VkBufferView viewB, 7080 vk::DescriptorSetUpdateBuilder& updateBuilder, 7081 vk::Move<vk::VkDescriptorUpdateTemplateKHR>& updateTemplate, 7082 RawUpdateRegistry& updateRegistry, 7083 vk::VkPipelineLayout pipelineLayout) 7084 { 7085 const vk::VkDescriptorSetAllocateInfo allocInfo = 7086 { 7087 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, 7088 DE_NULL, 7089 pool, 7090 1u, 7091 &layout 7092 }; 7093 7094 vk::Move<vk::VkDescriptorSet> descriptorSet; 7095 if (updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH && updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE) 7096 { 7097 descriptorSet = allocateDescriptorSet(vki, device, &allocInfo); 7098 } 7099 else 7100 { 7101 descriptorSet = vk::Move<vk::VkDescriptorSet>(); 7102 } 7103 7104 if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_TEMPLATE) 7105 { 7106 writeDescriptorSetWithTemplate(vki, device, descriptorType, shaderInterface, layout, pool, viewA, viewB, *descriptorSet, updateTemplate, updateRegistry); 7107 } 7108 else if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE) 7109 { 7110 writeDescriptorSetWithTemplate(vki, device, descriptorType, shaderInterface, layout, pool, viewA, viewB, *descriptorSet, updateTemplate, updateRegistry, true, pipelineLayout); 7111 } 7112 else if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH) 7113 { 7114 writeDescriptorSet(vki, device, descriptorType, shaderInterface, layout, pool, viewA, viewB, *descriptorSet, updateBuilder, updateMethod); 7115 } 7116 else if (updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL) 7117 { 7118 writeDescriptorSet(vki, device, descriptorType, shaderInterface, layout, pool, viewA, viewB, *descriptorSet, updateBuilder); 7119 } 7120 7121 return descriptorSet; 7122 } 7123 7124 void TexelBufferRenderInstance::writeDescriptorSet (const vk::DeviceInterface& vki, 7125 vk::VkDevice device, 7126 vk::VkDescriptorType descriptorType, 7127 ShaderInputInterface shaderInterface, 7128 vk::VkDescriptorSetLayout layout, 7129 vk::VkDescriptorPool pool, 7130 vk::VkBufferView viewA, 7131 vk::VkBufferView viewB, 7132 vk::VkDescriptorSet descriptorSet, 7133 vk::DescriptorSetUpdateBuilder& updateBuilder, 7134 DescriptorUpdateMethod updateMethod) 7135 { 7136 DE_UNREF(layout); 7137 DE_UNREF(pool); 7138 const vk::VkBufferView texelBufferInfos[2] = 7139 { 7140 viewA, 7141 viewB, 7142 }; 7143 7144 switch (shaderInterface) 7145 { 7146 case SHADER_INPUT_SINGLE_DESCRIPTOR: 7147 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType, &texelBufferInfos[0]); 7148 break; 7149 7150 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS: 7151 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType, &texelBufferInfos[0]); 7152 updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), descriptorType, &texelBufferInfos[1]); 7153 break; 7154 7155 case SHADER_INPUT_DESCRIPTOR_ARRAY: 7156 updateBuilder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType, 2u, texelBufferInfos); 7157 break; 7158 7159 default: 7160 DE_FATAL("Impossible"); 7161 } 7162 7163 if (updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL) 7164 { 7165 updateBuilder.update(vki, device); 7166 } 7167 } 7168 7169 void TexelBufferRenderInstance::writeDescriptorSetWithTemplate (const vk::DeviceInterface& vki, 7170 vk::VkDevice device, 7171 vk::VkDescriptorType descriptorType, 7172 ShaderInputInterface shaderInterface, 7173 vk::VkDescriptorSetLayout layout, 7174 vk::VkDescriptorPool pool, 7175 vk::VkBufferView viewA, 7176 vk::VkBufferView viewB, 7177 vk::VkDescriptorSet descriptorSet, 7178 vk::Move<vk::VkDescriptorUpdateTemplateKHR>& updateTemplate, 7179 RawUpdateRegistry& updateRegistry, 7180 bool withPush, 7181 vk::VkPipelineLayout pipelineLayout) 7182 { 7183 DE_UNREF(pool); 7184 const vk::VkBufferView texelBufferInfos[2] = 7185 { 7186 viewA, 7187 viewB, 7188 }; 7189 std::vector<vk::VkDescriptorUpdateTemplateEntryKHR> updateEntries; 7190 vk::VkDescriptorUpdateTemplateCreateInfoKHR templateCreateInfo = 7191 { 7192 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR, 7193 DE_NULL, 7194 0, 7195 0, // updateCount 7196 DE_NULL, // pUpdates 7197 withPush ? vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR : vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR, 7198 layout, 7199 vk::VK_PIPELINE_BIND_POINT_GRAPHICS, 7200 pipelineLayout, 7201 0 7202 }; 7203 updateRegistry.addWriteObject(texelBufferInfos[0]); 7204 updateRegistry.addWriteObject(texelBufferInfos[1]); 7205 7206 switch (shaderInterface) 7207 { 7208 case SHADER_INPUT_SINGLE_DESCRIPTOR: 7209 updateEntries.push_back(createTemplateBinding(0, 0, 1, descriptorType, updateRegistry.getWriteObjectOffset(0), 0)); 7210 break; 7211 7212 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS: 7213 updateEntries.push_back(createTemplateBinding(0, 0, 1, descriptorType, updateRegistry.getWriteObjectOffset(0), 0)); 7214 updateEntries.push_back(createTemplateBinding(1, 0, 1, descriptorType, updateRegistry.getWriteObjectOffset(1), 0)); 7215 break; 7216 7217 case SHADER_INPUT_DESCRIPTOR_ARRAY: 7218 updateEntries.push_back(createTemplateBinding(0, 0, 2, descriptorType, updateRegistry.getWriteObjectOffset(0), sizeof(texelBufferInfos[0]))); 7219 break; 7220 7221 default: 7222 DE_FATAL("Impossible"); 7223 } 7224 7225 templateCreateInfo.pDescriptorUpdateEntries = &updateEntries[0]; 7226 templateCreateInfo.descriptorUpdateEntryCount = (deUint32)updateEntries.size(); 7227 7228 updateTemplate = vk::createDescriptorUpdateTemplateKHR(vki, device, &templateCreateInfo); 7229 7230 if (!withPush) 7231 { 7232 vki.updateDescriptorSetWithTemplateKHR(device, descriptorSet, *updateTemplate, updateRegistry.getRawPointer()); 7233 } 7234 } 7235 7236 void TexelBufferRenderInstance::logTestPlan (void) const 7237 { 7238 std::ostringstream msg; 7239 7240 msg << "Rendering 2x2 grid.\n" 7241 << "Single descriptor set. Descriptor set contains " 7242 << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" : 7243 (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? "two" : 7244 (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" : 7245 (const char*)DE_NULL) 7246 << " descriptor(s) of type " << vk::getDescriptorTypeName(m_descriptorType) << "\n" 7247 << "Buffer view is created with a " << ((m_nonzeroViewOffset) ? ("non-zero") : ("zero")) << " offset.\n" 7248 << "Buffer format is " << vk::getFormatName(vk::mapTextureFormat(m_texelBuffers.getTextureFormat())) << ".\n"; 7249 7250 if (m_stageFlags == 0u) 7251 { 7252 msg << "Descriptors are not accessed in any shader stage.\n"; 7253 } 7254 else 7255 { 7256 msg << "Color in each cell is fetched using the descriptor(s):\n"; 7257 7258 for (int resultNdx = 0; resultNdx < 4; ++resultNdx) 7259 { 7260 msg << "Test sample " << resultNdx << ": fetch at position " << m_texelBuffers.getFetchPos(resultNdx); 7261 7262 if (m_shaderInterface != SHADER_INPUT_SINGLE_DESCRIPTOR) 7263 { 7264 const int srcResourceNdx = (resultNdx % 2); // ABAB source 7265 msg << " from texelBuffer " << srcResourceNdx; 7266 } 7267 7268 msg << "\n"; 7269 } 7270 7271 msg << "Descriptors are accessed in {" 7272 << (((m_stageFlags & vk::VK_SHADER_STAGE_VERTEX_BIT) != 0) ? (" vertex") : ("")) 7273 << (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) != 0) ? (" tess_control") : ("")) 7274 << (((m_stageFlags & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) != 0) ? (" tess_evaluation") : ("")) 7275 << (((m_stageFlags & vk::VK_SHADER_STAGE_GEOMETRY_BIT) != 0) ? (" geometry") : ("")) 7276 << (((m_stageFlags & vk::VK_SHADER_STAGE_FRAGMENT_BIT) != 0) ? (" fragment") : ("")) 7277 << " } stages."; 7278 } 7279 7280 m_context.getTestContext().getLog() 7281 << tcu::TestLog::Message 7282 << msg.str() 7283 << tcu::TestLog::EndMessage; 7284 } 7285 7286 vk::VkPipelineLayout TexelBufferRenderInstance::getPipelineLayout (void) const 7287 { 7288 return *m_pipelineLayout; 7289 } 7290 7291 void TexelBufferRenderInstance::writeDrawCmdBuffer (vk::VkCommandBuffer cmd) const 7292 { 7293 if (m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE && m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH) 7294 { 7295 m_vki.cmdBindDescriptorSets(cmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, getPipelineLayout(), 0, 1, &m_descriptorSet.get(), 0, DE_NULL); 7296 } 7297 else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE) 7298 { 7299 m_vki.cmdPushDescriptorSetWithTemplateKHR(cmd, *m_updateTemplate, getPipelineLayout(), 0, (const void*)m_updateRegistry.getRawPointer()); 7300 } 7301 else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH) 7302 { 7303 m_updateBuilder.updateWithPush(m_vki, cmd, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0); 7304 } 7305 7306 m_vki.cmdDraw(cmd, 6 * 4, 1, 0, 0); // render four quads (two separate triangles) 7307 } 7308 7309 tcu::TestStatus TexelBufferRenderInstance::verifyResultImage (const tcu::ConstPixelBufferAccess& result) const 7310 { 7311 const tcu::Vec4 green (0.0f, 1.0f, 0.0f, 1.0f); 7312 const tcu::Vec4 yellow (1.0f, 1.0f, 0.0f, 1.0f); 7313 const bool doFetch = (m_stageFlags != 0u); // no active stages? Then don't fetch 7314 const tcu::Vec4 sample0 = (!doFetch) ? (yellow) : (m_texelBuffers.fetchTexelValue(0)); 7315 const tcu::Vec4 sample1 = (!doFetch) ? (green) : (m_texelBuffers.fetchTexelValue(1)); 7316 const tcu::Vec4 sample2 = (!doFetch) ? (green) : (m_texelBuffers.fetchTexelValue(2)); 7317 const tcu::Vec4 sample3 = (!doFetch) ? (yellow) : (m_texelBuffers.fetchTexelValue(3)); 7318 tcu::Surface reference (m_targetSize.x(), m_targetSize.y()); 7319 7320 drawQuadrantReferenceResult(reference.getAccess(), sample0, sample1, sample2, sample3); 7321 7322 if (!bilinearCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", reference.getAccess(), result, tcu::RGBA(1, 1, 1, 1), tcu::COMPARE_LOG_RESULT)) 7323 return tcu::TestStatus::fail("Image verification failed"); 7324 else 7325 return tcu::TestStatus::pass("Pass"); 7326 } 7327 7328 class TexelBufferComputeInstance : public vkt::TestInstance 7329 { 7330 public: 7331 TexelBufferComputeInstance (vkt::Context& context, 7332 DescriptorUpdateMethod updateMethod, 7333 vk::VkDescriptorType descriptorType, 7334 ShaderInputInterface shaderInterface, 7335 bool nonzeroViewOffset); 7336 7337 private: 7338 vk::Move<vk::VkDescriptorSetLayout> createDescriptorSetLayout (void) const; 7339 vk::Move<vk::VkDescriptorPool> createDescriptorPool (void) const; 7340 vk::Move<vk::VkDescriptorSet> createDescriptorSet (vk::VkDescriptorPool pool, vk::VkDescriptorSetLayout layout); 7341 void writeDescriptorSet (vk::VkDescriptorSet descriptorSet); 7342 void writeDescriptorSetWithTemplate (vk::VkDescriptorSet descriptorSet, vk::VkDescriptorSetLayout layout, bool withPush = false, vk::VkPipelineLayout pipelineLayout = DE_NULL); 7343 7344 tcu::TestStatus iterate (void); 7345 void logTestPlan (void) const; 7346 tcu::TestStatus testResourceAccess (void); 7347 7348 const DescriptorUpdateMethod m_updateMethod; 7349 const vk::VkDescriptorType m_descriptorType; 7350 const ShaderInputInterface m_shaderInterface; 7351 const bool m_nonzeroViewOffset; 7352 7353 const vk::DeviceInterface& m_vki; 7354 const vk::VkDevice m_device; 7355 const vk::VkQueue m_queue; 7356 const deUint32 m_queueFamilyIndex; 7357 vk::Allocator& m_allocator; 7358 vk::Move<vk::VkDescriptorUpdateTemplateKHR> m_updateTemplate; 7359 7360 const ComputeInstanceResultBuffer m_result; 7361 const TexelBufferInstanceBuffers m_texelBuffers; 7362 7363 RawUpdateRegistry m_updateRegistry; 7364 vk::DescriptorSetUpdateBuilder m_updateBuilder; 7365 }; 7366 7367 TexelBufferComputeInstance::TexelBufferComputeInstance (Context& context, 7368 DescriptorUpdateMethod updateMethod, 7369 vk::VkDescriptorType descriptorType, 7370 ShaderInputInterface shaderInterface, 7371 bool nonzeroViewOffset) 7372 : vkt::TestInstance (context) 7373 , m_updateMethod (updateMethod) 7374 , m_descriptorType (descriptorType) 7375 , m_shaderInterface (shaderInterface) 7376 , m_nonzeroViewOffset (nonzeroViewOffset) 7377 , m_vki (context.getDeviceInterface()) 7378 , m_device (context.getDevice()) 7379 , m_queue (context.getUniversalQueue()) 7380 , m_queueFamilyIndex (context.getUniversalQueueFamilyIndex()) 7381 , m_allocator (context.getDefaultAllocator()) 7382 , m_updateTemplate () 7383 , m_result (m_vki, m_device, m_allocator) 7384 , m_texelBuffers (m_vki, m_device, m_allocator, m_descriptorType, getInterfaceNumResources(m_shaderInterface), m_nonzeroViewOffset) 7385 , m_updateRegistry () 7386 , m_updateBuilder () 7387 { 7388 } 7389 7390 vk::Move<vk::VkDescriptorSetLayout> TexelBufferComputeInstance::createDescriptorSetLayout (void) const 7391 { 7392 vk::DescriptorSetLayoutBuilder builder; 7393 vk::VkDescriptorSetLayoutCreateFlags extraFlags = 0; 7394 7395 if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE || 7396 m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH) 7397 { 7398 extraFlags |= vk::VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR; 7399 } 7400 7401 builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT); 7402 7403 switch (m_shaderInterface) 7404 { 7405 case SHADER_INPUT_SINGLE_DESCRIPTOR: 7406 builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT); 7407 break; 7408 7409 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS: 7410 builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT); 7411 builder.addSingleBinding(m_descriptorType, vk::VK_SHADER_STAGE_COMPUTE_BIT); 7412 break; 7413 7414 case SHADER_INPUT_DESCRIPTOR_ARRAY: 7415 builder.addArrayBinding(m_descriptorType, 2u, vk::VK_SHADER_STAGE_COMPUTE_BIT); 7416 break; 7417 7418 default: 7419 DE_FATAL("Impossible"); 7420 }; 7421 7422 return builder.build(m_vki, m_device, extraFlags); 7423 } 7424 7425 vk::Move<vk::VkDescriptorPool> TexelBufferComputeInstance::createDescriptorPool (void) const 7426 { 7427 return vk::DescriptorPoolBuilder() 7428 .addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER) 7429 .addType(m_descriptorType, getInterfaceNumResources(m_shaderInterface)) 7430 .build(m_vki, m_device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1); 7431 } 7432 7433 vk::Move<vk::VkDescriptorSet> TexelBufferComputeInstance::createDescriptorSet (vk::VkDescriptorPool pool, vk::VkDescriptorSetLayout layout) 7434 { 7435 const vk::VkDescriptorSetAllocateInfo allocInfo = 7436 { 7437 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, 7438 DE_NULL, 7439 pool, 7440 1u, 7441 &layout 7442 }; 7443 7444 vk::Move<vk::VkDescriptorSet> descriptorSet; 7445 if (m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH && m_updateMethod != DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE) 7446 { 7447 descriptorSet = allocateDescriptorSet(m_vki, m_device, &allocInfo); 7448 } 7449 else 7450 { 7451 descriptorSet = vk::Move<vk::VkDescriptorSet>(); 7452 } 7453 7454 7455 if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_TEMPLATE) 7456 { 7457 writeDescriptorSetWithTemplate(*descriptorSet, layout); 7458 } 7459 else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL) 7460 { 7461 writeDescriptorSet(*descriptorSet); 7462 } 7463 7464 return descriptorSet; 7465 } 7466 7467 void TexelBufferComputeInstance::writeDescriptorSet (vk::VkDescriptorSet descriptorSet) 7468 { 7469 const vk::VkDescriptorBufferInfo resultInfo = vk::makeDescriptorBufferInfo(m_result.getBuffer(), 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE); 7470 const vk::VkBufferView texelBufferInfos[2] = 7471 { 7472 m_texelBuffers.getBufferViewA(), 7473 m_texelBuffers.getBufferViewB(), 7474 }; 7475 7476 // result 7477 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultInfo); 7478 7479 // texel buffers 7480 switch (m_shaderInterface) 7481 { 7482 case SHADER_INPUT_SINGLE_DESCRIPTOR: 7483 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), m_descriptorType, &texelBufferInfos[0]); 7484 break; 7485 7486 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS: 7487 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), m_descriptorType, &texelBufferInfos[0]); 7488 m_updateBuilder.writeSingle(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(2u), m_descriptorType, &texelBufferInfos[1]); 7489 break; 7490 7491 case SHADER_INPUT_DESCRIPTOR_ARRAY: 7492 m_updateBuilder.writeArray(descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), m_descriptorType, 2u, texelBufferInfos); 7493 break; 7494 7495 default: 7496 DE_FATAL("Impossible"); 7497 } 7498 7499 if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_NORMAL) 7500 { 7501 m_updateBuilder.update(m_vki, m_device); 7502 } 7503 } 7504 7505 void TexelBufferComputeInstance::writeDescriptorSetWithTemplate (vk::VkDescriptorSet descriptorSet, vk::VkDescriptorSetLayout layout, bool withPush, vk::VkPipelineLayout pipelineLayout) 7506 { 7507 const vk::VkDescriptorBufferInfo resultInfo = vk::makeDescriptorBufferInfo(m_result.getBuffer(), 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE); 7508 const vk::VkBufferView texelBufferInfos[2] = 7509 { 7510 m_texelBuffers.getBufferViewA(), 7511 m_texelBuffers.getBufferViewB(), 7512 }; 7513 std::vector<vk::VkDescriptorUpdateTemplateEntryKHR> updateEntries; 7514 vk::VkDescriptorUpdateTemplateCreateInfoKHR templateCreateInfo = 7515 { 7516 vk::VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR, 7517 DE_NULL, 7518 0, 7519 0, // updateCount 7520 DE_NULL, // pUpdates 7521 withPush ? vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR : vk::VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR, 7522 layout, 7523 vk::VK_PIPELINE_BIND_POINT_COMPUTE, 7524 pipelineLayout, 7525 0 7526 }; 7527 m_updateRegistry.addWriteObject(resultInfo); 7528 m_updateRegistry.addWriteObject(texelBufferInfos[0]); 7529 m_updateRegistry.addWriteObject(texelBufferInfos[1]); 7530 7531 // result 7532 updateEntries.push_back(createTemplateBinding(0, 0, 1, vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, m_updateRegistry.getWriteObjectOffset(0), 0)); 7533 7534 // texel buffers 7535 switch (m_shaderInterface) 7536 { 7537 case SHADER_INPUT_SINGLE_DESCRIPTOR: 7538 updateEntries.push_back(createTemplateBinding(1, 0, 1, m_descriptorType, m_updateRegistry.getWriteObjectOffset(1), 0)); 7539 break; 7540 7541 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS: 7542 updateEntries.push_back(createTemplateBinding(1, 0, 1, m_descriptorType, m_updateRegistry.getWriteObjectOffset(1), 0)); 7543 updateEntries.push_back(createTemplateBinding(2, 0, 1, m_descriptorType, m_updateRegistry.getWriteObjectOffset(2), 0)); 7544 break; 7545 7546 case SHADER_INPUT_DESCRIPTOR_ARRAY: 7547 updateEntries.push_back(createTemplateBinding(1, 0, 2, m_descriptorType, m_updateRegistry.getWriteObjectOffset(1), sizeof(texelBufferInfos[0]))); 7548 break; 7549 7550 default: 7551 DE_FATAL("Impossible"); 7552 } 7553 7554 templateCreateInfo.pDescriptorUpdateEntries = &updateEntries[0]; 7555 templateCreateInfo.descriptorUpdateEntryCount = (deUint32)updateEntries.size(); 7556 7557 m_updateTemplate = vk::createDescriptorUpdateTemplateKHR(m_vki, m_device, &templateCreateInfo); 7558 7559 if (!withPush) 7560 { 7561 m_vki.updateDescriptorSetWithTemplateKHR(m_device, descriptorSet, *m_updateTemplate, m_updateRegistry.getRawPointer()); 7562 } 7563 } 7564 7565 tcu::TestStatus TexelBufferComputeInstance::iterate (void) 7566 { 7567 logTestPlan(); 7568 return testResourceAccess(); 7569 } 7570 7571 void TexelBufferComputeInstance::logTestPlan (void) const 7572 { 7573 std::ostringstream msg; 7574 7575 msg << "Fetching 4 values from image in compute shader.\n" 7576 << "Single descriptor set. Descriptor set contains " 7577 << ((m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? "single" : 7578 (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? "two" : 7579 (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? "an array (size 2) of" : 7580 (const char*)DE_NULL) 7581 << " descriptor(s) of type " << vk::getDescriptorTypeName(m_descriptorType) << "\n" 7582 << "Buffer view is created with a " << ((m_nonzeroViewOffset) ? ("non-zero") : ("zero")) << " offset.\n" 7583 << "Buffer format is " << vk::getFormatName(vk::mapTextureFormat(m_texelBuffers.getTextureFormat())) << ".\n"; 7584 7585 for (int resultNdx = 0; resultNdx < 4; ++resultNdx) 7586 { 7587 msg << "Test sample " << resultNdx << ": fetch at position " << m_texelBuffers.getFetchPos(resultNdx); 7588 7589 if (m_shaderInterface != SHADER_INPUT_SINGLE_DESCRIPTOR) 7590 { 7591 const int srcResourceNdx = (resultNdx % 2); // ABAB source 7592 msg << " from texelBuffer " << srcResourceNdx; 7593 } 7594 7595 msg << "\n"; 7596 } 7597 7598 m_context.getTestContext().getLog() 7599 << tcu::TestLog::Message 7600 << msg.str() 7601 << tcu::TestLog::EndMessage; 7602 } 7603 7604 tcu::TestStatus TexelBufferComputeInstance::testResourceAccess (void) 7605 { 7606 const vk::Unique<vk::VkDescriptorSetLayout> descriptorSetLayout (createDescriptorSetLayout()); 7607 const vk::Unique<vk::VkDescriptorPool> descriptorPool (createDescriptorPool()); 7608 const vk::Unique<vk::VkDescriptorSet> descriptorSet (createDescriptorSet(*descriptorPool, *descriptorSetLayout)); 7609 const ComputePipeline pipeline (m_vki, m_device, m_context.getBinaryCollection(), 1, &descriptorSetLayout.get()); 7610 7611 const vk::VkDescriptorSet descriptorSets[] = { *descriptorSet }; 7612 const int numDescriptorSets = (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE || m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH) ? 0 : DE_LENGTH_OF_ARRAY(descriptorSets); 7613 const deUint32* const dynamicOffsets = DE_NULL; 7614 const int numDynamicOffsets = 0; 7615 const vk::VkBufferMemoryBarrier* const preBarriers = m_texelBuffers.getBufferInitBarriers(); 7616 const int numPreBarriers = m_texelBuffers.getNumTexelBuffers(); 7617 const vk::VkBufferMemoryBarrier* const postBarriers = m_result.getResultReadBarrier(); 7618 const int numPostBarriers = 1; 7619 7620 const ComputeCommand compute (m_vki, 7621 m_device, 7622 pipeline.getPipeline(), 7623 pipeline.getPipelineLayout(), 7624 tcu::UVec3(4, 1, 1), 7625 numDescriptorSets, descriptorSets, 7626 numDynamicOffsets, dynamicOffsets, 7627 numPreBarriers, preBarriers, 7628 numPostBarriers, postBarriers); 7629 7630 tcu::Vec4 results[4]; 7631 bool anyResultSet = false; 7632 bool allResultsOk = true; 7633 7634 if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE) 7635 { 7636 writeDescriptorSetWithTemplate(DE_NULL, *descriptorSetLayout, true, pipeline.getPipelineLayout()); 7637 compute.submitAndWait(m_queueFamilyIndex, m_queue, *m_updateTemplate, (const void*) m_updateRegistry.getRawPointer()); 7638 } 7639 else if (m_updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH) 7640 { 7641 writeDescriptorSet(DE_NULL); 7642 compute.submitAndWait(m_queueFamilyIndex, m_queue, m_updateBuilder); 7643 } 7644 else 7645 { 7646 compute.submitAndWait(m_queueFamilyIndex, m_queue); 7647 } 7648 m_result.readResultContentsTo(&results); 7649 7650 // verify 7651 for (int resultNdx = 0; resultNdx < 4; ++resultNdx) 7652 { 7653 const tcu::Vec4 result = results[resultNdx]; 7654 const tcu::Vec4 reference = m_texelBuffers.fetchTexelValue(resultNdx); 7655 const tcu::Vec4 conversionThreshold = tcu::Vec4(1.0f / 255.0f); 7656 7657 if (result != tcu::Vec4(-1.0f)) 7658 anyResultSet = true; 7659 7660 if (tcu::boolAny(tcu::greaterThan(tcu::abs(result - reference), conversionThreshold))) 7661 { 7662 allResultsOk = false; 7663 7664 m_context.getTestContext().getLog() 7665 << tcu::TestLog::Message 7666 << "Test sample " << resultNdx << ": Expected " << reference << ", got " << result 7667 << tcu::TestLog::EndMessage; 7668 } 7669 } 7670 7671 // read back and verify 7672 if (allResultsOk) 7673 return tcu::TestStatus::pass("Pass"); 7674 else if (anyResultSet) 7675 return tcu::TestStatus::fail("Invalid result values"); 7676 else 7677 { 7678 m_context.getTestContext().getLog() 7679 << tcu::TestLog::Message 7680 << "Result buffer was not written to." 7681 << tcu::TestLog::EndMessage; 7682 return tcu::TestStatus::fail("Result buffer was not written to"); 7683 } 7684 } 7685 7686 class TexelBufferDescriptorCase : public QuadrantRendederCase 7687 { 7688 public: 7689 enum 7690 { 7691 FLAG_VIEW_OFFSET = (1u << 1u), 7692 }; 7693 // enum continues where resource flags ends 7694 DE_STATIC_ASSERT((deUint32)FLAG_VIEW_OFFSET == (deUint32)RESOURCE_FLAG_LAST); 7695 7696 TexelBufferDescriptorCase (tcu::TestContext& testCtx, 7697 DescriptorUpdateMethod updateMethod, 7698 const char* name, 7699 const char* description, 7700 bool isPrimaryCmdBuf, 7701 vk::VkDescriptorType descriptorType, 7702 vk::VkShaderStageFlags exitingStages, 7703 vk::VkShaderStageFlags activeStages, 7704 ShaderInputInterface shaderInterface, 7705 deUint32 flags); 7706 7707 private: 7708 std::string genExtensionDeclarations (vk::VkShaderStageFlagBits stage) const; 7709 std::string genResourceDeclarations (vk::VkShaderStageFlagBits stage, int numUsedBindings) const; 7710 std::string genResourceAccessSource (vk::VkShaderStageFlagBits stage) const; 7711 std::string genNoAccessSource (void) const; 7712 7713 vkt::TestInstance* createInstance (vkt::Context& context) const; 7714 7715 const DescriptorUpdateMethod m_updateMethod; 7716 const bool m_isPrimaryCmdBuf; 7717 const vk::VkDescriptorType m_descriptorType; 7718 const ShaderInputInterface m_shaderInterface; 7719 const bool m_nonzeroViewOffset; 7720 }; 7721 7722 TexelBufferDescriptorCase::TexelBufferDescriptorCase (tcu::TestContext& testCtx, 7723 DescriptorUpdateMethod updateMethod, 7724 const char* name, 7725 const char* description, 7726 bool isPrimaryCmdBuf, 7727 vk::VkDescriptorType descriptorType, 7728 vk::VkShaderStageFlags exitingStages, 7729 vk::VkShaderStageFlags activeStages, 7730 ShaderInputInterface shaderInterface, 7731 deUint32 flags) 7732 : QuadrantRendederCase (testCtx, name, description, glu::GLSL_VERSION_310_ES, exitingStages, activeStages) 7733 , m_updateMethod (updateMethod) 7734 , m_isPrimaryCmdBuf (isPrimaryCmdBuf) 7735 , m_descriptorType (descriptorType) 7736 , m_shaderInterface (shaderInterface) 7737 , m_nonzeroViewOffset (((flags & FLAG_VIEW_OFFSET) != 0) ? (1u) : (0u)) 7738 { 7739 } 7740 7741 std::string TexelBufferDescriptorCase::genExtensionDeclarations (vk::VkShaderStageFlagBits stage) const 7742 { 7743 DE_UNREF(stage); 7744 return "#extension GL_EXT_texture_buffer : require\n"; 7745 } 7746 7747 std::string TexelBufferDescriptorCase::genResourceDeclarations (vk::VkShaderStageFlagBits stage, int numUsedBindings) const 7748 { 7749 DE_UNREF(stage); 7750 7751 const bool isUniform = isUniformDescriptorType(m_descriptorType); 7752 const char* const storageType = (isUniform) ? ("samplerBuffer ") : ("readonly imageBuffer "); 7753 const char* const formatQualifier = (isUniform) ? ("") : (", rgba8"); 7754 7755 switch (m_shaderInterface) 7756 { 7757 case SHADER_INPUT_SINGLE_DESCRIPTOR: 7758 return "layout(set = 0, binding = " + de::toString(numUsedBindings) + formatQualifier + ") uniform highp " + storageType + " u_texelBuffer;\n"; 7759 7760 case SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS: 7761 return "layout(set = 0, binding = " + de::toString(numUsedBindings) + formatQualifier + ") uniform highp " + storageType + " u_texelBufferA;\n" 7762 "layout(set = 0, binding = " + de::toString(numUsedBindings+1) + formatQualifier + ") uniform highp " + storageType + " u_texelBufferB;\n"; 7763 7764 case SHADER_INPUT_DESCRIPTOR_ARRAY: 7765 return "layout(set = 0, binding = " + de::toString(numUsedBindings) + formatQualifier + ") uniform highp " + storageType + " u_texelBuffer[2];\n"; 7766 7767 default: 7768 DE_FATAL("Impossible"); 7769 return ""; 7770 } 7771 } 7772 7773 std::string TexelBufferDescriptorCase::genResourceAccessSource (vk::VkShaderStageFlagBits stage) const 7774 { 7775 DE_UNREF(stage); 7776 7777 const char* const accessPostfixA = (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? ("") 7778 : (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? ("A") 7779 : (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? ("[0]") 7780 : (DE_NULL); 7781 const char* const accessPostfixB = (m_shaderInterface == SHADER_INPUT_SINGLE_DESCRIPTOR) ? ("") 7782 : (m_shaderInterface == SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS) ? ("B") 7783 : (m_shaderInterface == SHADER_INPUT_DESCRIPTOR_ARRAY) ? ("[1]") 7784 : (DE_NULL); 7785 const char* const fetchFunc = (isUniformDescriptorType(m_descriptorType)) ? ("texelFetch") : ("imageLoad"); 7786 std::ostringstream buf; 7787 7788 buf << " if (quadrant_id == 0)\n" 7789 << " result_color = " << fetchFunc << "(u_texelBuffer" << accessPostfixA << ", " << TexelBufferInstanceBuffers::getFetchPos(0) << ");\n" 7790 << " else if (quadrant_id == 1)\n" 7791 << " result_color = " << fetchFunc << "(u_texelBuffer" << accessPostfixB << ", " << TexelBufferInstanceBuffers::getFetchPos(1) << ");\n" 7792 << " else if (quadrant_id == 2)\n" 7793 << " result_color = " << fetchFunc << "(u_texelBuffer" << accessPostfixA << ", " << TexelBufferInstanceBuffers::getFetchPos(2) << ");\n" 7794 << " else\n" 7795 << " result_color = " << fetchFunc << "(u_texelBuffer" << accessPostfixB << ", " << TexelBufferInstanceBuffers::getFetchPos(3) << ");\n"; 7796 7797 return buf.str(); 7798 } 7799 7800 std::string TexelBufferDescriptorCase::genNoAccessSource (void) const 7801 { 7802 return " if (quadrant_id == 1 || quadrant_id == 2)\n" 7803 " result_color = vec4(0.0, 1.0, 0.0, 1.0);\n" 7804 " else\n" 7805 " result_color = vec4(1.0, 1.0, 0.0, 1.0);\n"; 7806 } 7807 7808 vkt::TestInstance* TexelBufferDescriptorCase::createInstance (vkt::Context& context) const 7809 { 7810 verifyDriverSupport(context.getDeviceFeatures(), context.getDeviceExtensions(), m_updateMethod, m_descriptorType, m_activeStages); 7811 7812 if (m_exitingStages == vk::VK_SHADER_STAGE_COMPUTE_BIT) 7813 { 7814 DE_ASSERT(m_isPrimaryCmdBuf); // secondaries are only valid within renderpass 7815 return new TexelBufferComputeInstance(context, m_updateMethod, m_descriptorType, m_shaderInterface, m_nonzeroViewOffset); 7816 } 7817 else 7818 return new TexelBufferRenderInstance(context, m_updateMethod, m_isPrimaryCmdBuf, m_descriptorType, m_activeStages, m_shaderInterface, m_nonzeroViewOffset); 7819 } 7820 7821 void createShaderAccessImageTests (tcu::TestCaseGroup* group, 7822 bool isPrimaryCmdBuf, 7823 DescriptorUpdateMethod updateMethod, 7824 vk::VkDescriptorType descriptorType, 7825 vk::VkShaderStageFlags exitingStages, 7826 vk::VkShaderStageFlags activeStages, 7827 ShaderInputInterface dimension, 7828 deUint32 resourceFlags) 7829 { 7830 static const struct 7831 { 7832 vk::VkImageViewType viewType; 7833 const char* name; 7834 const char* description; 7835 deUint32 flags; 7836 } s_imageTypes[] = 7837 { 7838 { vk::VK_IMAGE_VIEW_TYPE_1D, "1d", "1D image view", 0u }, 7839 { vk::VK_IMAGE_VIEW_TYPE_1D, "1d_base_mip", "1D image subview with base mip level", ImageDescriptorCase::FLAG_BASE_MIP }, 7840 { vk::VK_IMAGE_VIEW_TYPE_1D, "1d_base_slice", "1D image subview with base array slice", ImageDescriptorCase::FLAG_BASE_SLICE }, 7841 7842 { vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY, "1d_array", "1D array image view", 0u }, 7843 { vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY, "1d_array_base_mip", "1D array image subview with base mip level", ImageDescriptorCase::FLAG_BASE_MIP }, 7844 { vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY, "1d_array_base_slice", "1D array image subview with base array slice", ImageDescriptorCase::FLAG_BASE_SLICE }, 7845 7846 { vk::VK_IMAGE_VIEW_TYPE_2D, "2d", "2D image view", 0u }, 7847 { vk::VK_IMAGE_VIEW_TYPE_2D, "2d_base_mip", "2D image subview with base mip level", ImageDescriptorCase::FLAG_BASE_MIP }, 7848 { vk::VK_IMAGE_VIEW_TYPE_2D, "2d_base_slice", "2D image subview with base array slice", ImageDescriptorCase::FLAG_BASE_SLICE }, 7849 7850 { vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY, "2d_array", "2D array image view", 0u }, 7851 { vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY, "2d_array_base_mip", "2D array image subview with base mip level", ImageDescriptorCase::FLAG_BASE_MIP }, 7852 { vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY, "2d_array_base_slice", "2D array image subview with base array slice", ImageDescriptorCase::FLAG_BASE_SLICE }, 7853 7854 { vk::VK_IMAGE_VIEW_TYPE_3D, "3d", "3D image view", 0u }, 7855 { vk::VK_IMAGE_VIEW_TYPE_3D, "3d_base_mip", "3D image subview with base mip level", ImageDescriptorCase::FLAG_BASE_MIP }, 7856 // no 3d array textures 7857 7858 { vk::VK_IMAGE_VIEW_TYPE_CUBE, "cube", "Cube image view", 0u }, 7859 { vk::VK_IMAGE_VIEW_TYPE_CUBE, "cube_base_mip", "Cube image subview with base mip level", ImageDescriptorCase::FLAG_BASE_MIP }, 7860 { vk::VK_IMAGE_VIEW_TYPE_CUBE, "cube_base_slice", "Cube image subview with base array slice", ImageDescriptorCase::FLAG_BASE_SLICE }, 7861 7862 { vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, "cube_array", "Cube image view", 0u }, 7863 { vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, "cube_array_base_mip", "Cube image subview with base mip level", ImageDescriptorCase::FLAG_BASE_MIP }, 7864 { vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, "cube_array_base_slice", "Cube image subview with base array slice", ImageDescriptorCase::FLAG_BASE_SLICE }, 7865 }; 7866 7867 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_imageTypes); ++ndx) 7868 { 7869 // never overlap 7870 DE_ASSERT((s_imageTypes[ndx].flags & resourceFlags) == 0u); 7871 7872 // SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS only supported in VK_DESCRIPTOR_TYPE_SAMPLER on graphics shaders for now 7873 if (dimension == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS && 7874 (descriptorType != vk::VK_DESCRIPTOR_TYPE_SAMPLER || activeStages == vk::VK_SHADER_STAGE_COMPUTE_BIT)) 7875 continue; 7876 7877 group->addChild(new ImageDescriptorCase(group->getTestContext(), 7878 s_imageTypes[ndx].name, 7879 s_imageTypes[ndx].description, 7880 isPrimaryCmdBuf, 7881 updateMethod, 7882 descriptorType, 7883 exitingStages, 7884 activeStages, 7885 dimension, 7886 s_imageTypes[ndx].viewType, 7887 s_imageTypes[ndx].flags | resourceFlags)); 7888 } 7889 } 7890 7891 void createShaderAccessTexelBufferTests (tcu::TestCaseGroup* group, 7892 bool isPrimaryCmdBuf, 7893 DescriptorUpdateMethod updateMethod, 7894 vk::VkDescriptorType descriptorType, 7895 vk::VkShaderStageFlags exitingStages, 7896 vk::VkShaderStageFlags activeStages, 7897 ShaderInputInterface dimension, 7898 deUint32 resourceFlags) 7899 { 7900 DE_ASSERT(resourceFlags == 0); 7901 DE_UNREF(resourceFlags); 7902 7903 static const struct 7904 { 7905 const char* name; 7906 const char* description; 7907 deUint32 flags; 7908 } s_texelBufferTypes[] = 7909 { 7910 { "offset_zero", "View offset is zero", 0u }, 7911 { "offset_nonzero", "View offset is non-zero", TexelBufferDescriptorCase::FLAG_VIEW_OFFSET }, 7912 }; 7913 7914 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_texelBufferTypes); ++ndx) 7915 { 7916 if (dimension == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) 7917 continue; 7918 7919 group->addChild(new TexelBufferDescriptorCase(group->getTestContext(), 7920 updateMethod, 7921 s_texelBufferTypes[ndx].name, 7922 s_texelBufferTypes[ndx].description, 7923 isPrimaryCmdBuf, 7924 descriptorType, 7925 exitingStages, 7926 activeStages, 7927 dimension, 7928 s_texelBufferTypes[ndx].flags)); 7929 } 7930 } 7931 7932 void createShaderAccessBufferTests (tcu::TestCaseGroup* group, 7933 bool isPrimaryCmdBuf, 7934 DescriptorUpdateMethod updateMethod, 7935 vk::VkDescriptorType descriptorType, 7936 vk::VkShaderStageFlags exitingStages, 7937 vk::VkShaderStageFlags activeStages, 7938 ShaderInputInterface dimension, 7939 deUint32 resourceFlags) 7940 { 7941 DE_ASSERT(resourceFlags == 0u); 7942 DE_UNREF(resourceFlags); 7943 7944 static const struct 7945 { 7946 const char* name; 7947 const char* description; 7948 bool isForDynamicCases; 7949 deUint32 flags; 7950 } s_bufferTypes[] = 7951 { 7952 { "offset_view_zero", "View offset is zero", false, 0u }, 7953 { "offset_view_nonzero", "View offset is non-zero", false, BufferDescriptorCase::FLAG_VIEW_OFFSET }, 7954 7955 { "offset_view_zero_dynamic_zero", "View offset is zero, dynamic offset is zero", true, BufferDescriptorCase::FLAG_DYNAMIC_OFFSET_ZERO }, 7956 { "offset_view_zero_dynamic_nonzero", "View offset is zero, dynamic offset is non-zero", true, BufferDescriptorCase::FLAG_DYNAMIC_OFFSET_NONZERO }, 7957 { "offset_view_nonzero_dynamic_zero", "View offset is non-zero, dynamic offset is zero", true, BufferDescriptorCase::FLAG_VIEW_OFFSET | BufferDescriptorCase::FLAG_DYNAMIC_OFFSET_ZERO }, 7958 { "offset_view_nonzero_dynamic_nonzero", "View offset is non-zero, dynamic offset is non-zero", true, BufferDescriptorCase::FLAG_VIEW_OFFSET | BufferDescriptorCase::FLAG_DYNAMIC_OFFSET_NONZERO }, 7959 }; 7960 7961 const bool isDynamicCase = isDynamicDescriptorType(descriptorType); 7962 7963 if (isDynamicCase) 7964 { 7965 if (updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH || updateMethod == DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE) 7966 { 7967 // Can't support push descriptor sets with dynamic UBOs or SSBOs 7968 return; 7969 } 7970 } 7971 7972 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_bufferTypes); ++ndx) 7973 { 7974 if (dimension == SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS) 7975 continue; 7976 7977 if (isDynamicCase == s_bufferTypes[ndx].isForDynamicCases) 7978 group->addChild(new BufferDescriptorCase(group->getTestContext(), 7979 updateMethod, 7980 s_bufferTypes[ndx].name, 7981 s_bufferTypes[ndx].description, 7982 isPrimaryCmdBuf, 7983 descriptorType, 7984 exitingStages, 7985 activeStages, 7986 dimension, 7987 s_bufferTypes[ndx].flags)); 7988 } 7989 } 7990 7991 } // anonymous 7992 7993 tcu::TestCaseGroup* createShaderAccessTests (tcu::TestContext& testCtx) 7994 { 7995 static const struct 7996 { 7997 const bool isPrimary; 7998 const char* name; 7999 const char* description; 8000 } s_bindTypes[] = 8001 { 8002 { true, "primary_cmd_buf", "Bind in primary command buffer" }, 8003 { false, "secondary_cmd_buf", "Bind in secondary command buffer" }, 8004 }; 8005 static const struct 8006 { 8007 const DescriptorUpdateMethod method; 8008 const char* name; 8009 const char* description; 8010 } s_updateMethods[] = 8011 { 8012 { DESCRIPTOR_UPDATE_METHOD_NORMAL, "", "Use regular descriptor updates" }, 8013 { DESCRIPTOR_UPDATE_METHOD_WITH_TEMPLATE, "with_template", "Use descriptor update templates" }, 8014 { DESCRIPTOR_UPDATE_METHOD_WITH_PUSH, "with_push", "Use push descriptor updates" }, 8015 { DESCRIPTOR_UPDATE_METHOD_WITH_PUSH_TEMPLATE, "with_push_template", "Use push descriptor update templates" }, 8016 }; 8017 static const struct 8018 { 8019 const vk::VkDescriptorType descriptorType; 8020 const char* name; 8021 const char* description; 8022 deUint32 flags; 8023 } s_descriptorTypes[] = 8024 { 8025 { vk::VK_DESCRIPTOR_TYPE_SAMPLER, "sampler_mutable", "VK_DESCRIPTOR_TYPE_SAMPLER with mutable sampler", 0u }, 8026 { vk::VK_DESCRIPTOR_TYPE_SAMPLER, "sampler_immutable", "VK_DESCRIPTOR_TYPE_SAMPLER with immutable sampler", RESOURCE_FLAG_IMMUTABLE_SAMPLER }, 8027 { vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, "combined_image_sampler_mutable", "VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER with mutable sampler", 0u }, 8028 { vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, "combined_image_sampler_immutable", "VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER with immutable sampler", RESOURCE_FLAG_IMMUTABLE_SAMPLER }, 8029 // \note No way to access SAMPLED_IMAGE without a sampler 8030 //{ vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, "sampled_image", "VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE", 0u }, 8031 { vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, "storage_image", "VK_DESCRIPTOR_TYPE_STORAGE_IMAGE", 0u }, 8032 { vk::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, "uniform_texel_buffer", "VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER", 0u }, 8033 { vk::VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, "storage_texel_buffer", "VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER", 0u }, 8034 { vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, "uniform_buffer", "VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER", 0u }, 8035 { vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, "storage_buffer", "VK_DESCRIPTOR_TYPE_STORAGE_BUFFER", 0u }, 8036 { vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, "uniform_buffer_dynamic", "VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC", 0u }, 8037 { vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, "storage_buffer_dynamic", "VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC", 0u }, 8038 }; 8039 static const struct 8040 { 8041 const char* name; 8042 const char* description; 8043 vk::VkShaderStageFlags existingStages; //!< stages that exists 8044 vk::VkShaderStageFlags activeStages; //!< stages that access resource 8045 bool supportsSecondaryCmdBufs; 8046 } s_shaderStages[] = 8047 { 8048 { 8049 "no_access", 8050 "No accessing stages", 8051 vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT, 8052 0u, 8053 true, 8054 }, 8055 { 8056 "vertex", 8057 "Vertex stage", 8058 vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT, 8059 vk::VK_SHADER_STAGE_VERTEX_BIT, 8060 true, 8061 }, 8062 { 8063 "tess_ctrl", 8064 "Tessellation control stage", 8065 vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT, 8066 vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, 8067 true, 8068 }, 8069 { 8070 "tess_eval", 8071 "Tessellation evaluation stage", 8072 vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT, 8073 vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, 8074 true, 8075 }, 8076 { 8077 "geometry", 8078 "Geometry stage", 8079 vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_GEOMETRY_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT, 8080 vk::VK_SHADER_STAGE_GEOMETRY_BIT, 8081 true, 8082 }, 8083 { 8084 "fragment", 8085 "Fragment stage", 8086 vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT, 8087 vk::VK_SHADER_STAGE_FRAGMENT_BIT, 8088 true, 8089 }, 8090 { 8091 "compute", 8092 "Compute stage", 8093 vk::VK_SHADER_STAGE_COMPUTE_BIT, 8094 vk::VK_SHADER_STAGE_COMPUTE_BIT, 8095 false, 8096 }, 8097 { 8098 "vertex_fragment", 8099 "Vertex and fragment stages", 8100 vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT, 8101 vk::VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_FRAGMENT_BIT, 8102 true, 8103 }, 8104 }; 8105 static const struct 8106 { 8107 ShaderInputInterface dimension; 8108 const char* name; 8109 const char* description; 8110 } s_variableDimensions[] = 8111 { 8112 { SHADER_INPUT_SINGLE_DESCRIPTOR, "single_descriptor", "Single descriptor" }, 8113 { SHADER_INPUT_MULTIPLE_CONTIGUOUS_DESCRIPTORS, "multiple_contiguous_descriptors", "Multiple descriptors" }, 8114 { SHADER_INPUT_MULTIPLE_DISCONTIGUOUS_DESCRIPTORS, "multiple_discontiguous_descriptors", "Multiple descriptors" }, 8115 { SHADER_INPUT_DESCRIPTOR_ARRAY, "descriptor_array", "Descriptor array" }, 8116 }; 8117 8118 de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "shader_access", "Access resource via descriptor in a single descriptor set")); 8119 8120 // .primary_cmd_buf... 8121 for (int bindTypeNdx = 0; bindTypeNdx < DE_LENGTH_OF_ARRAY(s_bindTypes); ++bindTypeNdx) 8122 { 8123 de::MovePtr<tcu::TestCaseGroup> bindGroup(new tcu::TestCaseGroup(testCtx, s_bindTypes[bindTypeNdx].name, s_bindTypes[bindTypeNdx].description)); 8124 8125 for (int updateMethodNdx = 0; updateMethodNdx < DE_LENGTH_OF_ARRAY(s_updateMethods); ++updateMethodNdx) 8126 { 8127 de::MovePtr<tcu::TestCaseGroup> updateMethodGroup(new tcu::TestCaseGroup(testCtx, s_updateMethods[updateMethodNdx].name, s_updateMethods[updateMethodNdx].description)); 8128 8129 // .sampler, .combined_image_sampler, other resource types ... 8130 for (int descriptorNdx = 0; descriptorNdx < DE_LENGTH_OF_ARRAY(s_descriptorTypes); ++descriptorNdx) 8131 { 8132 de::MovePtr<tcu::TestCaseGroup> typeGroup(new tcu::TestCaseGroup(testCtx, s_descriptorTypes[descriptorNdx].name, s_descriptorTypes[descriptorNdx].description)); 8133 8134 for (int stageNdx = 0; stageNdx < DE_LENGTH_OF_ARRAY(s_shaderStages); ++stageNdx) 8135 { 8136 if (s_bindTypes[bindTypeNdx].isPrimary || s_shaderStages[stageNdx].supportsSecondaryCmdBufs) 8137 { 8138 de::MovePtr<tcu::TestCaseGroup> stageGroup(new tcu::TestCaseGroup(testCtx, s_shaderStages[stageNdx].name, s_shaderStages[stageNdx].description)); 8139 8140 for (int dimensionNdx = 0; dimensionNdx < DE_LENGTH_OF_ARRAY(s_variableDimensions); ++dimensionNdx) 8141 { 8142 de::MovePtr<tcu::TestCaseGroup> dimensionGroup(new tcu::TestCaseGroup(testCtx, s_variableDimensions[dimensionNdx].name, s_variableDimensions[dimensionNdx].description)); 8143 void (*createTestsFunc)(tcu::TestCaseGroup* group, 8144 bool isPrimaryCmdBuf, 8145 DescriptorUpdateMethod updateMethod, 8146 vk::VkDescriptorType descriptorType, 8147 vk::VkShaderStageFlags existingStages, 8148 vk::VkShaderStageFlags activeStages, 8149 ShaderInputInterface dimension, 8150 deUint32 resourceFlags); 8151 8152 switch (s_descriptorTypes[descriptorNdx].descriptorType) 8153 { 8154 case vk::VK_DESCRIPTOR_TYPE_SAMPLER: 8155 case vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: 8156 case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: 8157 createTestsFunc = createShaderAccessImageTests; 8158 break; 8159 8160 case vk::VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: 8161 case vk::VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: 8162 createTestsFunc = createShaderAccessTexelBufferTests; 8163 break; 8164 8165 case vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: 8166 case vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: 8167 case vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: 8168 case vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: 8169 createTestsFunc = createShaderAccessBufferTests; 8170 break; 8171 8172 default: 8173 createTestsFunc = DE_NULL; 8174 DE_FATAL("Impossible"); 8175 } 8176 8177 if (createTestsFunc) 8178 { 8179 createTestsFunc(dimensionGroup.get(), 8180 s_bindTypes[bindTypeNdx].isPrimary, 8181 s_updateMethods[updateMethodNdx].method, 8182 s_descriptorTypes[descriptorNdx].descriptorType, 8183 s_shaderStages[stageNdx].existingStages, 8184 s_shaderStages[stageNdx].activeStages, 8185 s_variableDimensions[dimensionNdx].dimension, 8186 s_descriptorTypes[descriptorNdx].flags); 8187 } 8188 else 8189 DE_FATAL("Impossible"); 8190 8191 stageGroup->addChild(dimensionGroup.release()); 8192 } 8193 8194 typeGroup->addChild(stageGroup.release()); 8195 } 8196 } 8197 8198 if (s_updateMethods[updateMethodNdx].method != DESCRIPTOR_UPDATE_METHOD_NORMAL) 8199 { 8200 updateMethodGroup->addChild(typeGroup.release()); 8201 } 8202 else 8203 { 8204 bindGroup->addChild(typeGroup.release()); 8205 } 8206 } 8207 8208 if (s_updateMethods[updateMethodNdx].method != DESCRIPTOR_UPDATE_METHOD_NORMAL) 8209 { 8210 bindGroup->addChild(updateMethodGroup.release()); 8211 } 8212 } 8213 8214 group->addChild(bindGroup.release()); 8215 } 8216 8217 return group.release(); 8218 } 8219 8220 } // BindingModel 8221 } // vkt 8222