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