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