1/*------------------------------------------------------------------------ 2 * Vulkan Conformance Tests 3 * ------------------------ 4 * 5 * Copyright (c) 2022 The Khronos Group Inc. 6 * Copyright (c) 2022 Google LLC. 7 * Copyright (c) 2023 LunarG, Inc. 8 * Copyright (c) 2023 Nintendo 9 * 10 * Licensed under the Apache License, Version 2.0 (the "License"); 11 * you may not use this file except in compliance with the License. 12 * You may obtain a copy of the License at 13 * 14 * http://www.apache.org/licenses/LICENSE-2.0 15 * 16 * Unless required by applicable law or agreed to in writing, software 17 * distributed under the License is distributed on an "AS IS" BASIS, 18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 * See the License for the specific language governing permissions and 20 * limitations under the License. 21 * 22 *//*! 23 * \file 24 * \brief 25 *//*--------------------------------------------------------------------*/ 26 27#include "vktPipelineImage2DViewOf3DTests.hpp" 28#include "vkPipelineConstructionUtil.hpp" 29#include "vktTestCase.hpp" 30#include "vkImageUtil.hpp" 31#include "vkPrograms.hpp" 32#include "vkTypeUtil.hpp" 33#include "vkObjUtil.hpp" 34#include "vkCmdUtil.hpp" 35#include "vkBuilderUtil.hpp" 36#include "vkImageWithMemory.hpp" 37#include "vkBufferWithMemory.hpp" 38#include "vkBarrierUtil.hpp" 39#include "tcuTexture.hpp" 40#include "tcuPlatform.hpp" 41#include "tcuImageCompare.hpp" 42#include "deMemory.h" 43 44#include <sstream> 45#include <vector> 46 47namespace vkt 48{ 49namespace pipeline 50{ 51 52using namespace vk; 53using de::MovePtr; 54 55namespace 56{ 57enum ImageAccessType { 58 StorageImage = 0, 59 Sampler, 60 CombinedImageSampler 61}; 62 63enum TestType { 64 Compute, 65 Fragment 66}; 67 68struct TestParameters { 69 tcu::IVec3 imageSize; 70 uint32_t mipLevel; 71 int32_t layerNdx; 72 ImageAccessType imageType; 73 TestType testType; 74 VkFormat imageFormat; 75 PipelineConstructionType pipelineConstructionType; 76}; 77 78inline int32_t computeMipLevelDimension (int32_t baseLevelDimension, uint32_t mipLevel) 79{ 80 return de::max(baseLevelDimension >> mipLevel, 1); 81} 82 83tcu::IVec3 computeMipLevelSize (tcu::IVec3 baseLevelSize, uint32_t mipLevel) 84{ 85 int32_t width = computeMipLevelDimension(baseLevelSize.x(), mipLevel); 86 int32_t height = computeMipLevelDimension(baseLevelSize.y(), mipLevel); 87 int32_t depth = computeMipLevelDimension(baseLevelSize.z(), mipLevel); 88 return tcu::IVec3(width, height, depth); 89} 90 91void copyImageLayerToBuffer (const DeviceInterface& vk, 92 VkCommandBuffer cmdBuffer, 93 VkImage image, 94 VkBuffer buffer, 95 tcu::IVec2 size, 96 VkAccessFlags srcAccessMask, 97 VkImageLayout oldLayout, 98 deUint32 layerToCopy, 99 uint32_t mipLevel) 100{ 101 const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, mipLevel, 1u, 0, 1u); 102 const VkImageMemoryBarrier imageBarrier = 103 { 104 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType 105 DE_NULL, // const void* pNext 106 srcAccessMask, // VkAccessFlags srcAccessMask 107 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask 108 oldLayout, // VkImageLayout oldLayout 109 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout 110 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex 111 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex 112 image, // VkImage image 113 subresourceRange // VkImageSubresourceRange subresourceRange 114 }; 115 116 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 117 0u, DE_NULL, 0u, DE_NULL, 1u, &imageBarrier); 118 119 const VkImageSubresourceLayers subresource = 120 { 121 subresourceRange.aspectMask, // VkImageAspectFlags aspectMask 122 mipLevel, // deUint32 mipLevel 123 0u, // deUint32 baseArrayLayer 124 1u, // deUint32 layerCount 125 }; 126 127 const VkBufferImageCopy region = 128 { 129 0ull, // VkDeviceSize bufferOffset 130 0u, // deUint32 bufferRowLength 131 0u, // deUint32 bufferImageHeight 132 subresource, // VkImageSubresourceLayers imageSubresource 133 makeOffset3D(0, 0, (int)layerToCopy), // VkOffset3D imageOffset 134 makeExtent3D(size.x(), size.y(), 1u) // VkExtent3D imageExtent 135 }; 136 137 vk.cmdCopyImageToBuffer(cmdBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, buffer, 1u, ®ion); 138 139 const VkBufferMemoryBarrier bufferBarrier = 140 { 141 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType 142 DE_NULL, // const void* pNext 143 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask 144 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask 145 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex 146 VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex 147 buffer, // VkBuffer buffer 148 0ull, // VkDeviceSize offset 149 VK_WHOLE_SIZE // VkDeviceSize size 150 }; 151 152 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 153 0u, DE_NULL, 1u, &bufferBarrier, 0u, DE_NULL); 154} 155 156// Draws a chess pattern to the given 'layer' (z-dimension) of the 'image'. Other layers will be cleared to white. 157void fillImage (const tcu::PixelBufferAccess& image, const int layer) 158{ 159 const tcu::Vec4 clearColor = tcu::Vec4(1); // White clear color. 160 for (int z = 0; z < image.getSize().z(); ++z) 161 for (int y = 0; y < image.getSize().y(); ++y) 162 for (int x = 0; x < image.getSize().x(); ++x) 163 { 164 if (z == layer) 165 { 166 const float c = (float)((x + y) & 1); 167 const tcu::Vec4 color = tcu::Vec4(c, c, c, 1.0f); 168 image.setPixel(color, x, y, z); 169 } 170 else 171 { 172 image.setPixel(clearColor, x, y, z); 173 } 174 } 175} 176 177 178class Image2DView3DImageInstance : public vkt::TestInstance 179{ 180public: 181 Image2DView3DImageInstance (Context& context, 182 const TestParameters testParameters) 183 : vkt::TestInstance(context), 184 m_testParameters(testParameters) 185 {} 186 187 tcu::TestStatus iterate (void); 188private: 189 void runComputePipeline (const VkDescriptorSet& descriptorSet, 190 const VkDescriptorSetLayout descriptorSetLayout, 191 tcu::IVec3& testMipLevelSize, 192 VkCommandBuffer cmdBuffer, 193 VkImage image, 194 VkBuffer outputBuffer); 195 196 void runGraphicsPipeline (const VkDescriptorSet& descriptorSet, 197 const VkDescriptorSetLayout descriptorSetLayout, 198 tcu::IVec3& testMipLevelSize, 199 VkCommandBuffer cmdBuffer, 200 VkImage image, 201 VkBuffer outputBuffer); 202 const TestParameters m_testParameters; 203}; 204 205void Image2DView3DImageInstance::runComputePipeline (const VkDescriptorSet& descriptorSet, 206 const VkDescriptorSetLayout descriptorSetLayout, 207 tcu::IVec3& testMipLevelSize, 208 VkCommandBuffer cmdBuffer, 209 VkImage image, 210 VkBuffer outputBuffer) 211{ 212 const DeviceInterface& vk = m_context.getDeviceInterface(); 213 const VkDevice device = m_context.getDevice(); 214 const VkQueue queue = m_context.getUniversalQueue(); 215 const bool useSampler = m_testParameters.imageType != StorageImage; 216 217 const Unique<VkShaderModule> shaderModule (createShaderModule(vk, device, m_context.getBinaryCollection().get("comp"), 0u)); 218 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout(vk, device, descriptorSetLayout)); 219 const Unique<VkPipeline> pipeline (makeComputePipeline(vk, device, *pipelineLayout, *shaderModule)); 220 221 vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline); 222 vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL); 223 vk.cmdDispatch(cmdBuffer, testMipLevelSize.x(), testMipLevelSize.y(), 1u); 224 225 // Copy the result image to a buffer. 226 copyImageLayerToBuffer(vk, cmdBuffer, image, outputBuffer, testMipLevelSize.xy(), VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL, useSampler ? 0u : m_testParameters.layerNdx, useSampler ? 0u : m_testParameters.mipLevel); 227 228 endCommandBuffer(vk, cmdBuffer); 229 230 // Wait for completion. 231 submitCommandsAndWait(vk, device, queue, cmdBuffer); 232} 233 234void Image2DView3DImageInstance::runGraphicsPipeline (const VkDescriptorSet& descriptorSet, 235 const VkDescriptorSetLayout descriptorSetLayout, 236 tcu::IVec3& testMipLevelSize, 237 VkCommandBuffer cmdBuffer, 238 VkImage image, 239 VkBuffer outputBuffer) 240{ 241 const InstanceInterface& vki = m_context.getInstanceInterface(); 242 const DeviceInterface& vk = m_context.getDeviceInterface(); 243 const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice(); 244 const VkDevice device = m_context.getDevice(); 245 const VkQueue queue = m_context.getUniversalQueue(); 246 const bool useSampler = m_testParameters.imageType != StorageImage; 247 248 const ShaderWrapper vertShader (ShaderWrapper(vk, device, m_context.getBinaryCollection().get("vert"), 0u)); 249 const ShaderWrapper fragShader (ShaderWrapper(vk, device, m_context.getBinaryCollection().get("frag"), 0u)); 250 const PipelineLayoutWrapper pipelineLayout (m_testParameters.pipelineConstructionType, vk, device, descriptorSetLayout); 251 RenderPassWrapper renderPass (m_testParameters.pipelineConstructionType, vk, device); 252 const std::vector<VkViewport> viewport = {makeViewport (m_testParameters.imageSize.x(), m_testParameters.imageSize.y())}; 253 const std::vector<VkRect2D> scissor = {makeRect2D (m_testParameters.imageSize.x(), m_testParameters.imageSize.y())}; 254 255 const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCreateInfo = 256 { 257 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType 258 DE_NULL, // const void* pNext 259 0u, // VkPipelineInputAssemblyStateCreateFlags flags 260 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN, // VkPrimitiveTopology topology 261 VK_FALSE // VkBool32 primitiveRestartEnable 262 }; 263 264 const VkVertexInputBindingDescription vertexInputBindingDescription = 265 { 266 0u, // deUint32 binding 267 sizeof(tcu::Vec4), // deUint32 stride 268 VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate 269 }; 270 271 const VkVertexInputAttributeDescription vertexInputAttributeDescription = 272 { 273 0u, // deUint32 location 274 0u, // deUint32 binding 275 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format 276 0u // deUint32 offset 277 }; 278 279 const VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfoDefault = 280 { 281 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType 282 DE_NULL, // const void* pNext 283 (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags 284 1u, // deUint32 vertexBindingDescriptionCount 285 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions 286 1u, // deUint32 vertexAttributeDescriptionCount 287 &vertexInputAttributeDescription // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions 288 }; 289 290 vk::GraphicsPipelineWrapper graphicsPipeline (vki, vk, physicalDevice, device, m_context.getDeviceExtensions(), m_testParameters.pipelineConstructionType, 0u); 291 graphicsPipeline.setMonolithicPipelineLayout(pipelineLayout) 292 .setDefaultDepthStencilState() 293 .setDefaultRasterizationState() 294 .setDefaultMultisampleState() 295 .setupVertexInputState(&vertexInputStateCreateInfoDefault, &inputAssemblyStateCreateInfo) 296 .setupPreRasterizationShaderState(viewport, 297 scissor, 298 pipelineLayout, 299 *renderPass, 300 0u, 301 vertShader) 302 .setupFragmentShaderState(pipelineLayout, *renderPass, 0u, fragShader) 303 .setupFragmentOutputState(*renderPass, 0u) 304 .buildPipeline(); 305 306 renderPass.createFramebuffer(vk, device, 0u, DE_NULL, DE_NULL, testMipLevelSize.x(), testMipLevelSize.y()); 307 308 // Create vertex buffer and fill it with full screen quad. 309 const std::vector<tcu::Vec4> vertexData = { 310 {-1, -1, 1, 1}, 311 { 1, -1, 1, 1}, 312 { 1, 1, 1, 1}, 313 {-1, 1, 1, 1}, 314 }; 315 size_t vertexBufferSize = sizeof(tcu::Vec4) * vertexData.size(); 316 BufferWithMemory vertexBuffer( 317 vk, 318 device, 319 m_context.getDefaultAllocator(), 320 makeBufferCreateInfo(vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), 321 MemoryRequirement::HostVisible); 322 deMemcpy(vertexBuffer.getAllocation().getHostPtr(), vertexData.data(), vertexBufferSize); 323 flushAlloc(vk, device, vertexBuffer.getAllocation()); 324 325 VkDeviceSize vertexBufferOffset = 0; 326 vk.cmdBindVertexBuffers(cmdBuffer, 0, 1, &*vertexBuffer, &vertexBufferOffset); 327 328 graphicsPipeline.bind(cmdBuffer); 329 vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL); 330 331 renderPass.begin(vk, cmdBuffer, makeRect2D(testMipLevelSize.xy())); 332 vk.cmdDraw(cmdBuffer, 4, 1, 0, 0); 333 renderPass.end(vk, cmdBuffer); 334 335 // Copy the result image to a buffer. 336 copyImageLayerToBuffer(vk, cmdBuffer, image, outputBuffer, testMipLevelSize.xy(), VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL, useSampler ? 0u : m_testParameters.layerNdx, useSampler ? 0u : m_testParameters.mipLevel); 337 338 endCommandBuffer(vk, cmdBuffer); 339 340 // Wait for completion. 341 submitCommandsAndWait(vk, device, queue, cmdBuffer); 342} 343 344tcu::TestStatus Image2DView3DImageInstance::iterate (void) 345{ 346 const DeviceInterface& vk = m_context.getDeviceInterface(); 347 const VkDevice device = m_context.getDevice(); 348 const VkQueue queue = m_context.getUniversalQueue(); 349 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); 350 Allocator& allocator = m_context.getDefaultAllocator(); 351 tcu::IVec3 imageSize = m_testParameters.imageSize; 352 const bool useSampler = m_testParameters.imageType != StorageImage; 353 const tcu::TextureFormat textureFormat = mapVkFormat(m_testParameters.imageFormat); 354 const uint32_t mipLevelCount = 3; 355 356 tcu::IVec3 testMipLevelSize = computeMipLevelSize(m_testParameters.imageSize, m_testParameters.mipLevel); 357 uint32_t bufferSize = testMipLevelSize.x() * testMipLevelSize.y() * testMipLevelSize.z() * textureFormat.getPixelSize(); 358 const BufferWithMemory outputBuffer (vk, device, allocator, makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT), MemoryRequirement::HostVisible); 359 360 // Input image is used with sampler cases only. 361 de::MovePtr<BufferWithMemory> inputImageBuffer; 362 363 // Upload the test image data for sampler cases. 364 if (useSampler) 365 { 366 // Initialize the input image's mip level and fill the target layer with a chess pattern, others will be white. 367 tcu::TextureLevel inputImageMipLevel (textureFormat, testMipLevelSize.x(), testMipLevelSize.y(), testMipLevelSize.z()); 368 fillImage(inputImageMipLevel.getAccess(), m_testParameters.layerNdx); 369 370 // Create a buffer to upload the image. 371 const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT); 372 inputImageBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible)); 373 374 // Upload target mip level to the input buffer. 375 deMemcpy(inputImageBuffer->getAllocation().getHostPtr(), inputImageMipLevel.getAccess().getDataPtr(), bufferSize); 376 flushAlloc(vk, device, inputImageBuffer->getAllocation()); 377 } 378 379 // Create the test image: sampled image or storage image, depending on the test type. 380 const VkImageUsageFlags usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | 381 VK_IMAGE_USAGE_TRANSFER_DST_BIT | 382 (useSampler ? VK_IMAGE_USAGE_SAMPLED_BIT : VK_IMAGE_USAGE_STORAGE_BIT); 383 const VkImageCreateInfo imageCreateInfo = 384 { 385 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType 386 DE_NULL, // const void* pNext 387 VK_IMAGE_CREATE_2D_VIEW_COMPATIBLE_BIT_EXT, // VkImageCreateFlags flags 388 VK_IMAGE_TYPE_3D, // VkImageType imageType 389 m_testParameters.imageFormat, // VkFormat format 390 makeExtent3D(imageSize.x(), imageSize.y(), imageSize.z()), // VkExtent3D extent 391 (uint32_t)mipLevelCount, // uint32_t mipLevels 392 1u, // uint32_t arrayLayers 393 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples 394 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling 395 usage, // VkImageUsageFlags usage 396 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode 397 0u, // uint32_t queueFamilyIndexCount 398 DE_NULL, // const uint32_t* pQueueFamilyIndices 399 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout 400 }; 401 ImageWithMemory testImage (vk, device, allocator, imageCreateInfo, MemoryRequirement::Any); 402 403 // Make an image view covering one of the mip levels. 404 const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, m_testParameters.mipLevel, 1u, m_testParameters.layerNdx, 1u); 405 const Unique<VkImageView> imageView (makeImageView(vk, device, *testImage, VK_IMAGE_VIEW_TYPE_2D, m_testParameters.imageFormat, subresourceRange)); 406 407 // resultImage is used in sampler / combined image sampler tests to verify the sampled image. 408 MovePtr<ImageWithMemory> resultImage; 409 Move<VkImageView> resultImageView; 410 Move<VkSampler> sampler; 411 if (useSampler) 412 { 413 const VkImageCreateInfo resultImageCreateInfo = 414 { 415 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType 416 DE_NULL, // const void* pNext 417 0U, // VkImageCreateFlags flags 418 VK_IMAGE_TYPE_2D, // VkImageType imageType 419 m_testParameters.imageFormat, // VkFormat format 420 makeExtent3D(testMipLevelSize.x(), testMipLevelSize.y(), 1), // VkExtent3D extent 421 1u, // deUint32 mipLevels 422 1u, // deUint32 arrayLayers 423 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples 424 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling 425 VK_IMAGE_USAGE_STORAGE_BIT | 426 VK_IMAGE_USAGE_TRANSFER_SRC_BIT | 427 VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage 428 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode 429 0u, // deUint32 queueFamilyIndexCount 430 DE_NULL, // const deUint32* pQueueFamilyIndices 431 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout 432 }; 433 434 resultImage = MovePtr<ImageWithMemory>(new ImageWithMemory(vk, device, allocator, resultImageCreateInfo, MemoryRequirement::Any)); 435 const VkImageSubresourceRange resultImgSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u); 436 resultImageView = makeImageView(vk, device, **resultImage, VK_IMAGE_VIEW_TYPE_2D, m_testParameters.imageFormat, resultImgSubresourceRange); 437 438 const VkSamplerCreateInfo samplerCreateInfo = 439 { 440 VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // VkStructureType sType 441 DE_NULL, // const void* pNext 442 (VkSamplerCreateFlags)0, // VkSamplerCreateFlags flags 443 VK_FILTER_NEAREST, // VkFilter magFilter 444 VK_FILTER_NEAREST, // VkFilter minFilter 445 VK_SAMPLER_MIPMAP_MODE_NEAREST, // VkSamplerMipmapMode mipmapMode 446 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeU 447 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeV 448 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeW 449 0.0f, // float mipLodBias 450 VK_FALSE, // VkBool32 anisotropyEnable 451 1.0f, // float maxAnisotropy 452 VK_FALSE, // VkBool32 compareEnable 453 VK_COMPARE_OP_ALWAYS, // VkCompareOp compareOp 454 0.0f, // float minLod 455 1.0f, // float maxLod 456 VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, // VkBorderColor borderColor 457 VK_FALSE, // VkBool32 unnormalizedCoordinates 458 }; 459 sampler = createSampler(vk, device, &samplerCreateInfo); 460 } 461 462 463 // Create the descriptor set. 464 DescriptorSetLayoutBuilder descriptorSetLayoutBuilder; 465 DescriptorPoolBuilder descriptorPoolBuilder; 466 467 VkShaderStageFlags shaderStage = m_testParameters.testType == Compute ? VK_SHADER_STAGE_COMPUTE_BIT : VK_SHADER_STAGE_FRAGMENT_BIT; 468 VkPipelineStageFlags pipelineStage = m_testParameters.testType == Compute ? VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT : VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; 469 switch (m_testParameters.imageType) 470 { 471 case StorageImage: 472 descriptorSetLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, shaderStage); 473 descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE); 474 break; 475 case Sampler: 476 descriptorSetLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, shaderStage); 477 descriptorSetLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_SAMPLER, shaderStage); 478 descriptorSetLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, shaderStage); 479 descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE); 480 descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_SAMPLER); 481 descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE); 482 break; 483 case CombinedImageSampler: 484 descriptorSetLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, shaderStage); 485 descriptorSetLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, shaderStage); 486 descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER); 487 descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE); 488 break; 489 default: 490 TCU_THROW(InternalError, "Unimplemented testImage type."); 491 } 492 493 if (useSampler) 494 { 495 // Clear the result image. 496 clearColorImage(vk, device, queue, m_context.getUniversalQueueFamilyIndex(), **resultImage, tcu::Vec4(0,0,0,1), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, pipelineStage, 0u, 1u); 497 } 498 else 499 { 500 // Clear the test image. 501 clearColorImage(vk, device, queue, m_context.getUniversalQueueFamilyIndex(), testImage.get(), tcu::Vec4(0,0,0,1), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, pipelineStage, 0u, 1u, 0u, mipLevelCount); 502 } 503 504 // Prepare the command buffer. 505 const Unique<VkCommandPool> cmdPool (makeCommandPool(vk, device, queueFamilyIndex)); 506 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY)); 507 508 // Start recording commands. 509 beginCommandBuffer(vk, *cmdBuffer); 510 511 if (useSampler) 512 { 513 // Copy the input image to the target mip level. 514 std::vector<VkBufferImageCopy> copies; 515 copies.push_back(makeBufferImageCopy(makeExtent3D(testMipLevelSize), makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, m_testParameters.mipLevel, 0, 1))); 516 copyBufferToImage(vk, *cmdBuffer, **inputImageBuffer, bufferSize, copies, VK_IMAGE_ASPECT_COLOR_BIT, mipLevelCount, 1u, *testImage, VK_IMAGE_LAYOUT_GENERAL, pipelineStage); 517 } 518 519 const Move<VkDescriptorSetLayout> descriptorSetLayout (descriptorSetLayoutBuilder.build(vk, device)); 520 const Move<VkDescriptorPool> descriptorPool (descriptorPoolBuilder.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u)); 521 const Unique<VkDescriptorSet> descriptorSet (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout)); 522 const VkDescriptorImageInfo testImageDescriptorInfo = makeDescriptorImageInfo(*sampler, *imageView, VK_IMAGE_LAYOUT_GENERAL); 523 524 // Write descriptor update. 525 { 526 DescriptorSetUpdateBuilder descriptorSetUpdateBuilder; 527 uint32_t bindingIdx = 0; 528 529 switch (m_testParameters.imageType) 530 { 531 case StorageImage: 532 descriptorSetUpdateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &testImageDescriptorInfo); 533 break; 534 case Sampler: 535 descriptorSetUpdateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(bindingIdx++), VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, &testImageDescriptorInfo); 536 descriptorSetUpdateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(bindingIdx++), VK_DESCRIPTOR_TYPE_SAMPLER, &testImageDescriptorInfo); 537 break; 538 case CombinedImageSampler: 539 descriptorSetUpdateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(bindingIdx++), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &testImageDescriptorInfo); 540 break; 541 } 542 543 if (useSampler) 544 { 545 const VkDescriptorImageInfo resultImageDescriptorInfo = makeDescriptorImageInfo(DE_NULL, *resultImageView, VK_IMAGE_LAYOUT_GENERAL); 546 descriptorSetUpdateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(bindingIdx), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &resultImageDescriptorInfo); 547 } 548 549 descriptorSetUpdateBuilder.update(vk, device); 550 } 551 552 if (m_testParameters.testType == Compute) 553 runComputePipeline(*descriptorSet, *descriptorSetLayout, testMipLevelSize, *cmdBuffer, useSampler ? **resultImage : *testImage, *outputBuffer); 554 else 555 runGraphicsPipeline(*descriptorSet, *descriptorSetLayout, testMipLevelSize, *cmdBuffer, useSampler ? **resultImage : *testImage, *outputBuffer); 556 557 // Validate the results. 558 { 559 // Create a reference image. 560 // The reference image has always a depth of 1, because it will be compared to the 2D result image (sampler cases) or to a single layer of a 3D image. 561 tcu::TextureLevel referenceImage (textureFormat, testMipLevelSize.x(), testMipLevelSize.y(), 1u); 562 fillImage(referenceImage.getAccess(), 0u); 563 564 const Allocation& outputBufferAllocation = outputBuffer.getAllocation(); 565 invalidateAlloc(vk, device, outputBufferAllocation); 566 567 const deUint32* bufferPtr = static_cast<deUint32*>(outputBufferAllocation.getHostPtr()); 568 tcu::ConstPixelBufferAccess pixelBufferAccess (mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM), testMipLevelSize.x(), testMipLevelSize.y(), 1u, bufferPtr); 569 570 if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Result", "Result comparison", referenceImage, pixelBufferAccess, tcu::Vec4(0.01f), tcu::COMPARE_LOG_ON_ERROR)) 571 return tcu::TestStatus::fail("Pixel comparison failed."); 572 573 } 574 575 return tcu::TestStatus::pass("pass"); 576} 577 578class ComputeImage2DView3DImageTest : public vkt::TestCase 579{ 580public: 581 ComputeImage2DView3DImageTest (tcu::TestContext& testContext, 582 const char* name, 583 const TestParameters& testParameters) 584 : vkt::TestCase (testContext, name), 585 m_testParameters (testParameters) {} 586 virtual ~ComputeImage2DView3DImageTest (void) {} 587 588 virtual void initPrograms (SourceCollections& sourceCollections) const; 589 virtual void checkSupport (Context& context) const; 590 virtual TestInstance* createInstance (Context& context) const; 591private: 592 const TestParameters m_testParameters; 593}; 594 595 596void ComputeImage2DView3DImageTest::checkSupport (Context& context) const 597{ 598 DE_ASSERT(m_testParameters.pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC); 599 600 if (!context.isDeviceFunctionalitySupported("VK_EXT_image_2d_view_of_3d")) 601 TCU_THROW(NotSupportedError, "VK_EXT_image_2d_view_of_3d functionality not supported."); 602 603 if (!context.getImage2DViewOf3DFeaturesEXT().image2DViewOf3D) 604 TCU_THROW(NotSupportedError, "image2DViewOf3D not supported."); 605 606 if (m_testParameters.imageType != StorageImage && !context.getImage2DViewOf3DFeaturesEXT().sampler2DViewOf3D) 607 TCU_THROW(NotSupportedError, "sampler2DViewOf3D not supported."); 608} 609 610void ComputeImage2DView3DImageTest::initPrograms (SourceCollections& sourceCollections) const 611{ 612 std::ostringstream src; 613 tcu::IVec3 mipLevelSize = computeMipLevelSize(m_testParameters.imageSize, m_testParameters.mipLevel); 614 if (m_testParameters.imageType == StorageImage) 615 { 616 src << "#version 450 core\n" 617 << "layout (local_size_x = 1, local_size_y = 1) in;\n" 618 << "layout (binding = 0, rgba8) writeonly uniform highp image2D storageImage;\n" 619 << "void main (void) {\n" 620 << " ivec2 uv = ivec2(gl_GlobalInvocationID.xy);\n" 621 << " float c = float((uv.x + uv.y) & 1);\n" 622 << " vec4 color = vec4(c, c, c, 1.0);\n" 623 << " imageStore(storageImage, uv, color);\n" 624 << "}\n"; 625 } 626 else if (m_testParameters.imageType == Sampler) 627 { 628 src << "#version 450 core\n" 629 << "layout (local_size_x = 1, local_size_y = 1) in;\n" 630 << "layout (set=0, binding = 0) uniform texture2D image;\n" 631 << "layout (set=0, binding = 1) uniform sampler samp;\n" 632 << "layout (rgba8, set=0, binding = 2) writeonly uniform highp image2D verifyImage;\n" 633 << "void main (void) {\n" 634 << " ivec2 uv = ivec2(gl_GlobalInvocationID.xy);\n" 635 << " vec2 texCoord = vec2(gl_GlobalInvocationID.xy) / " << mipLevelSize.x() <<".0;\n" 636 << " vec4 color = texture(sampler2D(image, samp), texCoord);\n" 637 << " imageStore(verifyImage, uv, color);\n" 638 << "}\n"; 639 } 640 else if (m_testParameters.imageType == CombinedImageSampler) 641 { 642 src << "#version 450 core\n" 643 << "layout (local_size_x = 1, local_size_y = 1) in;\n" 644 << "layout (binding = 0) uniform sampler2D combinedSampler;\n" 645 << "layout (rgba8, set=0, binding=1) writeonly uniform highp image2D verifyImage;\n" 646 << "void main (void) {\n" 647 << " ivec2 uv = ivec2(gl_GlobalInvocationID.xy);\n" 648 << " vec2 texCoord = vec2(gl_GlobalInvocationID.xy) / " << mipLevelSize.x() <<".0;\n" 649 << " vec4 color = texture(combinedSampler, texCoord);\n" 650 << " imageStore(verifyImage, uv, color);\n" 651 << "}\n"; 652 } 653 654 sourceCollections.glslSources.add("comp") << glu::ComputeSource(src.str()); 655} 656 657TestInstance* ComputeImage2DView3DImageTest::createInstance (Context& context) const 658{ 659 return new Image2DView3DImageInstance(context, m_testParameters); 660} 661 662class FragmentImage2DView3DImageTest : public vkt::TestCase 663{ 664public: 665 FragmentImage2DView3DImageTest (tcu::TestContext& testContext, 666 const char* name, 667 const TestParameters& testParameters) 668 : vkt::TestCase (testContext, name), 669 m_testParameters (testParameters) {} 670 virtual ~FragmentImage2DView3DImageTest (void) {} 671 672 virtual void initPrograms (SourceCollections& sourceCollections) const; 673 virtual void checkSupport (Context& context) const; 674 virtual TestInstance* createInstance (Context& context) const; 675private: 676 const TestParameters m_testParameters; 677}; 678 679void FragmentImage2DView3DImageTest::initPrograms (SourceCollections& sourceCollections) const 680{ 681 std::stringstream vertShader; 682 vertShader << "#version 450 core\n" 683 << "layout(location = 0) in vec4 in_position;\n" 684 << "out gl_PerVertex {\n" 685 << " vec4 gl_Position;\n" 686 << " float gl_PointSize;\n" 687 << "};\n" 688 << "void main() {\n" 689 << " gl_PointSize = 1.0;\n" 690 << " gl_Position = in_position;\n" 691 << "}\n"; 692 sourceCollections.glslSources.add("vert") << glu::VertexSource(vertShader.str()); 693 694 tcu::IVec3 mipLevelSize = computeMipLevelSize(m_testParameters.imageSize, m_testParameters.mipLevel); 695 std::stringstream fragShader; 696 if (m_testParameters.imageType == StorageImage) 697 { 698 fragShader << "#version 450 core\n" 699 << "layout(rgba8, set = 0, binding = 0) uniform image2D storageImage;\n" 700 << "void main()\n" 701 << "{\n" 702 << " ivec2 uv = ivec2(gl_FragCoord.xy);\n" 703 << " float c = float((uv.x + uv.y) & 1);\n" 704 << " vec4 color = vec4(c, c, c, 1.0);\n" 705 << " imageStore(storageImage, uv, color);\n" 706 << "}\n"; 707 } 708 709 else if (m_testParameters.imageType == Sampler) 710 { 711 fragShader << "#version 450 core\n" 712 << "layout (set = 0, binding = 0) uniform texture2D image;\n" 713 << "layout (set = 0, binding = 1) uniform sampler samp;\n" 714 << "layout (rgba8, set = 0, binding = 2) uniform image2D verifyImage;\n" 715 << "void main (void) {\n" 716 << " ivec2 uv = ivec2(gl_FragCoord.xy);\n" 717 << " vec2 texCoord = gl_FragCoord.xy / " << mipLevelSize.x() <<".0;\n" 718 << " vec4 color = texture(sampler2D(image, samp), texCoord);\n" 719 << " imageStore(verifyImage, uv, color);\n" 720 << "}\n"; 721 } 722 else if (m_testParameters.imageType == CombinedImageSampler) 723 { 724 fragShader << "#version 450 core\n" 725 << "layout (set = 0, binding = 0) uniform sampler2D combinedSampler;\n" 726 << "layout (rgba8, set = 0, binding = 1) uniform image2D verifyImage;\n" 727 << "void main (void) {\n" 728 << " ivec2 uv = ivec2(gl_FragCoord.xy);\n" 729 << " vec2 texCoord = gl_FragCoord.xy / " << mipLevelSize.x() <<".0;\n" 730 << " vec4 color = texture(combinedSampler, texCoord);\n" 731 << " imageStore(verifyImage, uv, color);\n" 732 << "}\n"; 733 } 734 sourceCollections.glslSources.add("frag") << glu::FragmentSource(fragShader.str()); 735} 736 737void FragmentImage2DView3DImageTest::checkSupport (Context& context) const 738{ 739 checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_testParameters.pipelineConstructionType); 740 741 if (!context.isDeviceFunctionalitySupported("VK_EXT_image_2d_view_of_3d")) 742 TCU_THROW(NotSupportedError, "VK_EXT_image_2d_view_of_3d functionality not supported."); 743 744 if (!context.getImage2DViewOf3DFeaturesEXT().image2DViewOf3D) 745 TCU_THROW(NotSupportedError, "image2DViewOf3D not supported."); 746 747 if (m_testParameters.imageType != StorageImage && !context.getImage2DViewOf3DFeaturesEXT().sampler2DViewOf3D) 748 TCU_THROW(NotSupportedError, "texture2DViewOf3D not supported."); 749 750 if (!context.getDeviceFeatures().fragmentStoresAndAtomics) 751 TCU_THROW(NotSupportedError, "fragmentStoresAndAtomics not supported"); 752} 753 754TestInstance* FragmentImage2DView3DImageTest::createInstance (Context& context) const 755{ 756 return new Image2DView3DImageInstance(context, m_testParameters); 757} 758 759} // anonymous 760 761tcu::TestCaseGroup* createImage2DViewOf3DTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType) 762{ 763 de::MovePtr<tcu::TestCaseGroup> imageTests (new tcu::TestCaseGroup(testCtx, "image_2d_view_3d_image")); 764 de::MovePtr<tcu::TestCaseGroup> computeGroup (new tcu::TestCaseGroup(testCtx, "compute")); 765 de::MovePtr<tcu::TestCaseGroup> fragmentGroup (new tcu::TestCaseGroup(testCtx, "fragment")); 766 767 const struct { 768 const ImageAccessType imageType; 769 const std::string name; 770 } imageAccessTypes [] { 771 { StorageImage, "storage" }, 772 { Sampler, "sampler" }, 773 { CombinedImageSampler, "combined_image_sampler" } 774 }; 775 776 const int32_t imageDimension = 64; 777 for (const auto& imageAccessType : imageAccessTypes) 778 { 779 de::MovePtr<tcu::TestCaseGroup> computeSubGroup (new tcu::TestCaseGroup(testCtx, imageAccessType.name.c_str())); 780 de::MovePtr<tcu::TestCaseGroup> fragmentSubGroup (new tcu::TestCaseGroup(testCtx, imageAccessType.name.c_str())); 781 for (uint32_t mipLevel = 0; mipLevel < 3; mipLevel += 2) 782 { 783 // Test the first and the last layer of the mip level. 784 std::vector<int32_t> layers = { 0, computeMipLevelDimension(imageDimension, mipLevel) -1 }; 785 for (const auto& layer : layers) 786 { 787 TestParameters testParameters { 788 tcu::IVec3(imageDimension), // IVec3 imageSize 789 mipLevel, // uint32_t mipLevel 790 layer, // int32_t layerNdx 791 imageAccessType.imageType, // ImageAccessType imageType 792 Fragment, // TestType testType 793 VK_FORMAT_R8G8B8A8_UNORM, // VkFormat imageFormat 794 pipelineConstructionType // PipelineConstructionType pipelineConstructionType 795 }; 796 std::string testName = "mip" + std::to_string(mipLevel) + "_layer" + std::to_string(layer); 797 fragmentSubGroup->addChild(new FragmentImage2DView3DImageTest(testCtx, testName.c_str(), testParameters)); 798 799 if (pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC) 800 { 801 testParameters.testType = Compute; 802 computeSubGroup->addChild(new ComputeImage2DView3DImageTest(testCtx, testName.c_str(), testParameters)); 803 } 804 } 805 } 806 computeGroup->addChild(computeSubGroup.release()); 807 fragmentGroup->addChild(fragmentSubGroup.release()); 808 } 809 810 imageTests->addChild(computeGroup.release()); 811 imageTests->addChild(fragmentGroup.release()); 812 return imageTests.release(); 813} 814 815} // pipeline 816} // vkt 817