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