• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <cstdint>
45 #include <sstream>
46 #include <vector>
47 
48 namespace vkt
49 {
50 namespace pipeline
51 {
52 
53 using namespace vk;
54 using de::MovePtr;
55 
56 namespace
57 {
58 
59 using DeviceMemorySp = de::SharedPtr<vk::Unique<vk::VkDeviceMemory>>;
60 
61 enum ImageAccessType
62 {
63     StorageImage = 0,
64     Sampler,
65     CombinedImageSampler
66 };
67 
68 enum ImageBindingType
69 {
70     Normal = 0,
71     Sparse,
72 };
73 
74 enum TestType
75 {
76     Compute,
77     Fragment
78 };
79 
80 struct TestParameters
81 {
82     tcu::IVec3 imageSize;
83     uint32_t mipLevel;
84     int32_t layerNdx;
85     ImageAccessType imageType;
86     TestType testType;
87     VkFormat imageFormat;
88     PipelineConstructionType pipelineConstructionType;
89     ImageBindingType imageBindingType;
90 };
91 
computeMipLevelDimension(int32_t baseLevelDimension,uint32_t mipLevel)92 inline int32_t computeMipLevelDimension(int32_t baseLevelDimension, uint32_t mipLevel)
93 {
94     return de::max(baseLevelDimension >> mipLevel, 1);
95 }
96 
computeMipLevelSize(tcu::IVec3 baseLevelSize,uint32_t mipLevel)97 tcu::IVec3 computeMipLevelSize(tcu::IVec3 baseLevelSize, uint32_t mipLevel)
98 {
99     int32_t width  = computeMipLevelDimension(baseLevelSize.x(), mipLevel);
100     int32_t height = computeMipLevelDimension(baseLevelSize.y(), mipLevel);
101     int32_t depth  = computeMipLevelDimension(baseLevelSize.z(), mipLevel);
102     return tcu::IVec3(width, height, depth);
103 }
104 
copyImageLayerToBuffer(const DeviceInterface & vk,VkCommandBuffer cmdBuffer,VkImage image,VkBuffer buffer,tcu::IVec2 size,VkAccessFlags srcAccessMask,VkImageLayout oldLayout,uint32_t layerToCopy,uint32_t mipLevel)105 void copyImageLayerToBuffer(const DeviceInterface &vk, VkCommandBuffer cmdBuffer, VkImage image, VkBuffer buffer,
106                             tcu::IVec2 size, VkAccessFlags srcAccessMask, VkImageLayout oldLayout, uint32_t layerToCopy,
107                             uint32_t mipLevel)
108 {
109     const VkImageSubresourceRange subresourceRange =
110         makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, mipLevel, 1u, 0, 1u);
111     const VkImageMemoryBarrier imageBarrier = {
112         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType            sType
113         nullptr,                                // const void*                pNext
114         srcAccessMask,                          // VkAccessFlags            srcAccessMask
115         VK_ACCESS_TRANSFER_READ_BIT,            // VkAccessFlags            dstAccessMask
116         oldLayout,                              // VkImageLayout            oldLayout
117         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,   // VkImageLayout            newLayout
118         VK_QUEUE_FAMILY_IGNORED,                // uint32_t                    srcQueueFamilyIndex
119         VK_QUEUE_FAMILY_IGNORED,                // uint32_t                    destQueueFamilyIndex
120         image,                                  // VkImage                    image
121         subresourceRange                        // VkImageSubresourceRange    subresourceRange
122     };
123 
124     vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u,
125                           nullptr, 0u, nullptr, 1u, &imageBarrier);
126 
127     const VkImageSubresourceLayers subresource = {
128         subresourceRange.aspectMask, // VkImageAspectFlags    aspectMask
129         mipLevel,                    // uint32_t                mipLevel
130         0u,                          // uint32_t                baseArrayLayer
131         1u,                          // uint32_t                layerCount
132     };
133 
134     const VkBufferImageCopy region = {
135         0ull,                                 // VkDeviceSize                    bufferOffset
136         0u,                                   // uint32_t                        bufferRowLength
137         0u,                                   // uint32_t                        bufferImageHeight
138         subresource,                          // VkImageSubresourceLayers        imageSubresource
139         makeOffset3D(0, 0, (int)layerToCopy), // VkOffset3D                    imageOffset
140         makeExtent3D(size.x(), size.y(), 1u)  // VkExtent3D                    imageExtent
141     };
142 
143     vk.cmdCopyImageToBuffer(cmdBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, buffer, 1u, &region);
144 
145     const VkBufferMemoryBarrier bufferBarrier = {
146         VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType    sType
147         nullptr,                                 // const void*        pNext
148         VK_ACCESS_TRANSFER_WRITE_BIT,            // VkAccessFlags    srcAccessMask
149         VK_ACCESS_HOST_READ_BIT,                 // VkAccessFlags    dstAccessMask
150         VK_QUEUE_FAMILY_IGNORED,                 // uint32_t            srcQueueFamilyIndex
151         VK_QUEUE_FAMILY_IGNORED,                 // uint32_t            dstQueueFamilyIndex
152         buffer,                                  // VkBuffer            buffer
153         0ull,                                    // VkDeviceSize        offset
154         VK_WHOLE_SIZE                            // VkDeviceSize        size
155     };
156 
157     vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, nullptr, 1u,
158                           &bufferBarrier, 0u, nullptr);
159 }
160 
161 // Draws a chess pattern to the given 'layer' (z-dimension) of the 'image'. Other layers will be cleared to white.
fillImage(const tcu::PixelBufferAccess & image,const int layer)162 void fillImage(const tcu::PixelBufferAccess &image, const int layer)
163 {
164     const tcu::Vec4 clearColor = tcu::Vec4(1); // White clear color.
165     for (int z = 0; z < image.getSize().z(); ++z)
166         for (int y = 0; y < image.getSize().y(); ++y)
167             for (int x = 0; x < image.getSize().x(); ++x)
168             {
169                 if (z == layer)
170                 {
171                     const float c         = (float)((x + y) & 1);
172                     const tcu::Vec4 color = tcu::Vec4(c, c, c, 1.0f);
173                     image.setPixel(color, x, y, z);
174                 }
175                 else
176                 {
177                     image.setPixel(clearColor, x, y, z);
178                 }
179             }
180 }
181 
182 template <typename T>
makeVkSharedPtr(vk::Move<T> vkMove)183 inline de::SharedPtr<vk::Unique<T>> makeVkSharedPtr(vk::Move<T> vkMove)
184 {
185     return de::SharedPtr<vk::Unique<T>>(new vk::Unique<T>(vkMove));
186 }
187 
getMemoryType(const InstanceInterface & instance,const VkPhysicalDevice physicalDevice,const VkMemoryRequirements & objectMemoryRequirements,const MemoryRequirement & memoryRequirement,uint32_t & memTypeIdx)188 bool getMemoryType(const InstanceInterface &instance, const VkPhysicalDevice physicalDevice,
189                    const VkMemoryRequirements &objectMemoryRequirements, const MemoryRequirement &memoryRequirement,
190                    uint32_t &memTypeIdx)
191 {
192     bool memTypeFound = false;
193     const VkPhysicalDeviceMemoryProperties deviceMemoryProperties =
194         getPhysicalDeviceMemoryProperties(instance, physicalDevice);
195 
196     for (uint32_t memoryTypeIdx = 0; !memTypeFound && memoryTypeIdx < deviceMemoryProperties.memoryTypeCount;
197          ++memoryTypeIdx)
198     {
199         if ((objectMemoryRequirements.memoryTypeBits & (1u << memoryTypeIdx)) != 0 &&
200             memoryRequirement.matchesHeap(deviceMemoryProperties.memoryTypes[memoryTypeIdx].propertyFlags))
201         {
202             memTypeIdx   = memoryTypeIdx;
203             memTypeFound = true;
204         }
205     }
206     return memTypeFound;
207 }
208 
makeSparseMemoryBinding(const DeviceInterface & vk,const VkDevice device,const VkDeviceSize allocationSize,const uint32_t memoryType,const VkDeviceSize resourceOffset,const VkSparseMemoryBindFlags flags)209 VkSparseMemoryBind makeSparseMemoryBinding(const DeviceInterface &vk, const VkDevice device,
210                                            const VkDeviceSize allocationSize, const uint32_t memoryType,
211                                            const VkDeviceSize resourceOffset, const VkSparseMemoryBindFlags flags)
212 {
213     const VkMemoryAllocateInfo allocInfo = {
214         VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // VkStructureType sType;
215         nullptr,                                // const void* pNext;
216         allocationSize,                         // VkDeviceSize allocationSize;
217         memoryType,                             // uint32_t memoryTypeIndex;
218     };
219 
220     VkDeviceMemory deviceMemory = VK_NULL_HANDLE;
221     VK_CHECK(vk.allocateMemory(device, &allocInfo, VK_NULL_HANDLE, &deviceMemory));
222 
223     VkSparseMemoryBind memoryBind;
224 
225     memoryBind.resourceOffset = resourceOffset;
226     memoryBind.size           = allocationSize;
227     memoryBind.memory         = deviceMemory;
228     memoryBind.memoryOffset   = 0u;
229     memoryBind.flags          = flags;
230 
231     return memoryBind;
232 }
233 
234 class Image2DView3DImageInstance : public vkt::TestInstance
235 {
236 public:
Image2DView3DImageInstance(Context & context,const TestParameters testParameters)237     Image2DView3DImageInstance(Context &context, const TestParameters testParameters)
238         : vkt::TestInstance(context)
239         , m_testParameters(testParameters)
240     {
241     }
242 
243     tcu::TestStatus iterate(void);
244 
245 private:
246     void runComputePipeline(const VkDescriptorSet &descriptorSet, const VkDescriptorSetLayout descriptorSetLayout,
247                             tcu::IVec3 &testMipLevelSize, VkCommandBuffer cmdBuffer, VkImage image,
248                             VkBuffer outputBuffer, const VkSemaphore *sparseImageSemaphore);
249 
250     void runGraphicsPipeline(const VkDescriptorSet &descriptorSet, const VkDescriptorSetLayout descriptorSetLayout,
251                              tcu::IVec3 &testMipLevelSize, VkCommandBuffer cmdBuffer, VkImage image,
252                              VkBuffer outputBuffer, const VkSemaphore *sparseImageSemaphore);
253     const TestParameters m_testParameters;
254 };
255 
commonSubmission(const DeviceInterface & vk,const VkDevice & device,const VkQueue & queue,VkCommandBuffer & cmdBuffer,const VkSemaphore * sparseImageSemaphore)256 void commonSubmission(const DeviceInterface &vk, const VkDevice &device, const VkQueue &queue,
257                       VkCommandBuffer &cmdBuffer, const VkSemaphore *sparseImageSemaphore)
258 {
259     const VkPipelineStageFlags stageFlags[] = {VK_PIPELINE_STAGE_TRANSFER_BIT};
260     const uint32_t waitSemaphoreCount       = (sparseImageSemaphore != nullptr) ? 1u : 0u;
261     const VkPipelineStageFlags *waitStages  = (sparseImageSemaphore != nullptr) ? stageFlags : nullptr;
262     submitCommandsAndWait(vk, device, queue, cmdBuffer, /*useDeviceGroups*/ false, /*deviceMask*/ 1u,
263                           waitSemaphoreCount, sparseImageSemaphore, waitStages);
264 }
265 
runComputePipeline(const VkDescriptorSet & descriptorSet,const VkDescriptorSetLayout descriptorSetLayout,tcu::IVec3 & testMipLevelSize,VkCommandBuffer cmdBuffer,VkImage image,VkBuffer outputBuffer,const VkSemaphore * sparseImageSemaphore)266 void Image2DView3DImageInstance::runComputePipeline(const VkDescriptorSet &descriptorSet,
267                                                     const VkDescriptorSetLayout descriptorSetLayout,
268                                                     tcu::IVec3 &testMipLevelSize, VkCommandBuffer cmdBuffer,
269                                                     VkImage image, VkBuffer outputBuffer,
270                                                     const VkSemaphore *sparseImageSemaphore)
271 {
272     const DeviceInterface &vk = m_context.getDeviceInterface();
273     const VkDevice device     = m_context.getDevice();
274     const VkQueue queue       = m_context.getUniversalQueue();
275     const bool useSampler     = m_testParameters.imageType != StorageImage;
276 
277     const Unique<VkShaderModule> shaderModule(
278         createShaderModule(vk, device, m_context.getBinaryCollection().get("comp"), 0u));
279     const Unique<VkPipelineLayout> pipelineLayout(makePipelineLayout(vk, device, descriptorSetLayout));
280     const Unique<VkPipeline> pipeline(makeComputePipeline(vk, device, *pipelineLayout, *shaderModule));
281 
282     vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
283     vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &descriptorSet, 0u,
284                              nullptr);
285     vk.cmdDispatch(cmdBuffer, testMipLevelSize.x(), testMipLevelSize.y(), 1u);
286 
287     // Copy the result image to a buffer.
288     copyImageLayerToBuffer(vk, cmdBuffer, image, outputBuffer, testMipLevelSize.xy(), VK_ACCESS_SHADER_WRITE_BIT,
289                            VK_IMAGE_LAYOUT_GENERAL, useSampler ? 0u : m_testParameters.layerNdx,
290                            useSampler ? 0u : m_testParameters.mipLevel);
291 
292     endCommandBuffer(vk, cmdBuffer);
293 
294     // Wait for completion.
295     commonSubmission(vk, device, queue, cmdBuffer, sparseImageSemaphore);
296 }
297 
runGraphicsPipeline(const VkDescriptorSet & descriptorSet,const VkDescriptorSetLayout descriptorSetLayout,tcu::IVec3 & testMipLevelSize,VkCommandBuffer cmdBuffer,VkImage image,VkBuffer outputBuffer,const VkSemaphore * sparseImageSemaphore)298 void Image2DView3DImageInstance::runGraphicsPipeline(const VkDescriptorSet &descriptorSet,
299                                                      const VkDescriptorSetLayout descriptorSetLayout,
300                                                      tcu::IVec3 &testMipLevelSize, VkCommandBuffer cmdBuffer,
301                                                      VkImage image, VkBuffer outputBuffer,
302                                                      const VkSemaphore *sparseImageSemaphore)
303 {
304     const InstanceInterface &vki          = m_context.getInstanceInterface();
305     const DeviceInterface &vk             = m_context.getDeviceInterface();
306     const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
307     const VkDevice device                 = m_context.getDevice();
308     const VkQueue queue                   = m_context.getUniversalQueue();
309     const bool useSampler                 = m_testParameters.imageType != StorageImage;
310 
311     const ShaderWrapper vertShader(ShaderWrapper(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
312     const ShaderWrapper fragShader(ShaderWrapper(vk, device, m_context.getBinaryCollection().get("frag"), 0u));
313     const PipelineLayoutWrapper pipelineLayout(m_testParameters.pipelineConstructionType, vk, device,
314                                                descriptorSetLayout);
315     RenderPassWrapper renderPass(m_testParameters.pipelineConstructionType, vk, device);
316     const std::vector<VkViewport> viewport = {
317         makeViewport(m_testParameters.imageSize.x(), m_testParameters.imageSize.y())};
318     const std::vector<VkRect2D> scissor = {makeRect2D(m_testParameters.imageSize.x(), m_testParameters.imageSize.y())};
319 
320     const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCreateInfo = {
321         VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType                            sType
322         nullptr,                                                     // const void*                                pNext
323         0u,                                                          // VkPipelineInputAssemblyStateCreateFlags    flags
324         VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN, // VkPrimitiveTopology                        topology
325         VK_FALSE                            // VkBool32                                    primitiveRestartEnable
326     };
327 
328     const VkVertexInputBindingDescription vertexInputBindingDescription = {
329         0u,                          // uint32_t                binding
330         sizeof(tcu::Vec4),           // uint32_t                stride
331         VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate    inputRate
332     };
333 
334     const VkVertexInputAttributeDescription vertexInputAttributeDescription = {
335         0u,                            // uint32_t        location
336         0u,                            // uint32_t        binding
337         VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat        format
338         0u                             // uint32_t        offset
339     };
340 
341     const VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfoDefault = {
342         VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType                                sType
343         nullptr,                                  // const void*                                    pNext
344         (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags        flags
345         1u,                             // uint32_t                                        vertexBindingDescriptionCount
346         &vertexInputBindingDescription, // const VkVertexInputBindingDescription*        pVertexBindingDescriptions
347         1u, // uint32_t                                        vertexAttributeDescriptionCount
348         &vertexInputAttributeDescription // const VkVertexInputAttributeDescription*        pVertexAttributeDescriptions
349     };
350 
351     vk::GraphicsPipelineWrapper graphicsPipeline(vki, vk, physicalDevice, device, m_context.getDeviceExtensions(),
352                                                  m_testParameters.pipelineConstructionType, 0u);
353     graphicsPipeline.setMonolithicPipelineLayout(pipelineLayout)
354         .setDefaultDepthStencilState()
355         .setDefaultRasterizationState()
356         .setDefaultMultisampleState()
357         .setupVertexInputState(&vertexInputStateCreateInfoDefault, &inputAssemblyStateCreateInfo)
358         .setupPreRasterizationShaderState(viewport, scissor, pipelineLayout, *renderPass, 0u, vertShader)
359         .setupFragmentShaderState(pipelineLayout, *renderPass, 0u, fragShader)
360         .setupFragmentOutputState(*renderPass, 0u)
361         .buildPipeline();
362 
363     renderPass.createFramebuffer(vk, device, 0u, nullptr, nullptr, testMipLevelSize.x(), testMipLevelSize.y());
364 
365     // Create vertex buffer and fill it with full screen quad.
366     const std::vector<tcu::Vec4> vertexData = {
367         {-1, -1, 1, 1},
368         {1, -1, 1, 1},
369         {1, 1, 1, 1},
370         {-1, 1, 1, 1},
371     };
372     size_t vertexBufferSize = sizeof(tcu::Vec4) * vertexData.size();
373     BufferWithMemory vertexBuffer(vk, device, m_context.getDefaultAllocator(),
374                                   makeBufferCreateInfo(vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT),
375                                   MemoryRequirement::HostVisible);
376     deMemcpy(vertexBuffer.getAllocation().getHostPtr(), vertexData.data(), vertexBufferSize);
377     flushAlloc(vk, device, vertexBuffer.getAllocation());
378 
379     VkDeviceSize vertexBufferOffset = 0;
380     vk.cmdBindVertexBuffers(cmdBuffer, 0, 1, &*vertexBuffer, &vertexBufferOffset);
381 
382     graphicsPipeline.bind(cmdBuffer);
383     vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet, 0u,
384                              nullptr);
385 
386     renderPass.begin(vk, cmdBuffer, makeRect2D(testMipLevelSize.xy()));
387     vk.cmdDraw(cmdBuffer, 4, 1, 0, 0);
388     renderPass.end(vk, cmdBuffer);
389 
390     // Copy the result image to a buffer.
391     copyImageLayerToBuffer(vk, cmdBuffer, image, outputBuffer, testMipLevelSize.xy(), VK_ACCESS_SHADER_WRITE_BIT,
392                            VK_IMAGE_LAYOUT_GENERAL, useSampler ? 0u : m_testParameters.layerNdx,
393                            useSampler ? 0u : m_testParameters.mipLevel);
394 
395     endCommandBuffer(vk, cmdBuffer);
396 
397     // Wait for completion.
398     commonSubmission(vk, device, queue, cmdBuffer, sparseImageSemaphore);
399 }
400 
iterate(void)401 tcu::TestStatus Image2DView3DImageInstance::iterate(void)
402 {
403     const DeviceInterface &vk              = m_context.getDeviceInterface();
404     const VkDevice device                  = m_context.getDevice();
405     const uint32_t queueFamilyIndex        = m_context.getUniversalQueueFamilyIndex();
406     Allocator &allocator                   = m_context.getDefaultAllocator();
407     tcu::IVec3 imageSize                   = m_testParameters.imageSize;
408     const bool useSampler                  = m_testParameters.imageType != StorageImage;
409     const bool useSparseBinding            = m_testParameters.imageBindingType == Sparse;
410     const tcu::TextureFormat textureFormat = mapVkFormat(m_testParameters.imageFormat);
411     const uint32_t mipLevelCount           = 3;
412 
413     tcu::IVec3 testMipLevelSize = computeMipLevelSize(m_testParameters.imageSize, m_testParameters.mipLevel);
414     uint32_t bufferSize =
415         testMipLevelSize.x() * testMipLevelSize.y() * testMipLevelSize.z() * textureFormat.getPixelSize();
416     const BufferWithMemory outputBuffer(vk, device, allocator,
417                                         makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT),
418                                         MemoryRequirement::HostVisible);
419 
420     // Input image is used with sampler cases only.
421     de::MovePtr<BufferWithMemory> inputImageBuffer;
422 
423     // Upload the test image data for sampler cases.
424     if (useSampler)
425     {
426         // Initialize the input image's mip level and fill the target layer with a chess pattern, others will be white.
427         tcu::TextureLevel inputImageMipLevel(textureFormat, testMipLevelSize.x(), testMipLevelSize.y(),
428                                              testMipLevelSize.z());
429         fillImage(inputImageMipLevel.getAccess(), m_testParameters.layerNdx);
430 
431         // Create a buffer to upload the image.
432         const VkBufferCreateInfo bufferCreateInfo =
433             makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
434         inputImageBuffer = de::MovePtr<BufferWithMemory>(
435             new BufferWithMemory(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible));
436 
437         // Upload target mip level to the input buffer.
438         deMemcpy(inputImageBuffer->getAllocation().getHostPtr(), inputImageMipLevel.getAccess().getDataPtr(),
439                  bufferSize);
440         flushAlloc(vk, device, inputImageBuffer->getAllocation());
441     }
442 
443     VkImageCreateFlags flags = VK_IMAGE_CREATE_2D_VIEW_COMPATIBLE_BIT_EXT;
444 
445     if (useSparseBinding)
446         flags |= VK_IMAGE_CREATE_SPARSE_BINDING_BIT;
447 
448     // Create the test image: sampled image or storage image, depending on the test type.
449     const VkImageUsageFlags usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
450                                     (useSampler ? VK_IMAGE_USAGE_SAMPLED_BIT : VK_IMAGE_USAGE_STORAGE_BIT);
451     const VkImageCreateInfo imageCreateInfo = {
452         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                       // VkStructureType            sType
453         nullptr,                                                   // const void*                pNext
454         flags,                                                     // VkImageCreateFlags        flags
455         VK_IMAGE_TYPE_3D,                                          // VkImageType                imageType
456         m_testParameters.imageFormat,                              // VkFormat                    format
457         makeExtent3D(imageSize.x(), imageSize.y(), imageSize.z()), // VkExtent3D                extent
458         (uint32_t)mipLevelCount,                                   // uint32_t                    mipLevels
459         1u,                                                        // uint32_t                    arrayLayers
460         VK_SAMPLE_COUNT_1_BIT,                                     // VkSampleCountFlagBits    samples
461         VK_IMAGE_TILING_OPTIMAL,                                   // VkImageTiling            tiling
462         usage,                                                     // VkImageUsageFlags        usage
463         VK_SHARING_MODE_EXCLUSIVE,                                 // VkSharingMode            sharingMode
464         0u,                                                        // uint32_t                    queueFamilyIndexCount
465         nullptr,                                                   // const uint32_t*            pQueueFamilyIndices
466         VK_IMAGE_LAYOUT_UNDEFINED,                                 // VkImageLayout            initialLayout
467     };
468 
469     de::MovePtr<ImageWithMemory> normalImage;
470     Move<VkImage> sparseImage;
471     Move<VkSemaphore> sparseImageSemaphore;
472     std::vector<DeviceMemorySp> deviceMemUniquePtrVec;
473 
474     if (!useSparseBinding)
475         // Create a normal image and bind device memory too
476         normalImage = de::MovePtr<ImageWithMemory>(
477             new ImageWithMemory(vk, device, allocator, imageCreateInfo, MemoryRequirement::Any));
478     else
479         // Create an image now and bind device memory later
480         sparseImage = createImage(vk, device, &imageCreateInfo);
481 
482     const VkImage &testImage = useSparseBinding ? sparseImage.get() : (*normalImage).get();
483 
484     if (useSparseBinding)
485     {
486         const InstanceInterface &instance     = m_context.getInstanceInterface();
487         const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
488         const VkQueue sparseQueue             = m_context.getSparseQueue();
489         std::vector<VkSparseMemoryBind> sparseMemoryBindings;
490 
491         const VkMemoryRequirements imageMemoryReqs = getImageMemoryRequirements(vk, device, testImage);
492 
493         if (imageMemoryReqs.size > getPhysicalDeviceProperties(instance, physicalDevice).limits.sparseAddressSpaceSize)
494             TCU_THROW(NotSupportedError, "Required memory size for sparse resource exceeds device limits");
495 
496         DE_ASSERT((imageMemoryReqs.size % imageMemoryReqs.alignment) == 0);
497 
498         uint32_t memoryType;
499         bool memoryTypeFound =
500             getMemoryType(instance, physicalDevice, imageMemoryReqs, MemoryRequirement::Any, memoryType);
501         if (!memoryTypeFound)
502             return tcu::TestStatus::fail("Required memory type for sparse resouce not found");
503 
504         const uint32_t numSparseBindings = static_cast<uint32_t>(imageMemoryReqs.size / imageMemoryReqs.alignment);
505         for (uint32_t bindingIdx = 0; bindingIdx < numSparseBindings; ++bindingIdx)
506         {
507             const VkSparseMemoryBind sparseMemoryBinding =
508                 makeSparseMemoryBinding(vk, device, imageMemoryReqs.alignment, memoryType,
509                                         imageMemoryReqs.alignment * bindingIdx, (VkSparseMemoryBindFlags)0u);
510 
511             deviceMemUniquePtrVec.push_back(makeVkSharedPtr(Move<VkDeviceMemory>(
512                 check<VkDeviceMemory>(sparseMemoryBinding.memory), Deleter<VkDeviceMemory>(vk, device, nullptr))));
513 
514             sparseMemoryBindings.push_back(sparseMemoryBinding);
515         }
516 
517         const VkSparseImageOpaqueMemoryBindInfo opaqueBindingInfo = makeSparseImageOpaqueMemoryBindInfo(
518             testImage, de::sizeU32(sparseMemoryBindings), de::dataOrNull(sparseMemoryBindings));
519 
520         sparseImageSemaphore = createSemaphore(vk, device);
521 
522         const VkBindSparseInfo bindSparseInfo = {
523             VK_STRUCTURE_TYPE_BIND_SPARSE_INFO, //VkStructureType sType;
524             nullptr,                            //const void* pNext;
525             0u,                                 //uint32_t waitSemaphoreCount;
526             nullptr,                            //const VkSemaphore* pWaitSemaphores;
527             0u,                                 //uint32_t bufferBindCount;
528             nullptr,                            //const VkSparseBufferMemoryBindInfo* pBufferBinds;
529             1u,                                 //uint32_t imageOpaqueBindCount;
530             &opaqueBindingInfo,                 //const VkSparseImageOpaqueMemoryBindInfo* pImageOpaqueBinds;
531             0u,                                 //uint32_t imageBindCount;
532             nullptr,                            //const VkSparseImageMemoryBindInfo* pImageBinds;
533             1u,                                 //uint32_t signalSemaphoreCount;
534             &sparseImageSemaphore.get()         //const VkSemaphore* pSignalSemaphores;
535         };
536 
537         VK_CHECK(vk.queueBindSparse(sparseQueue, 1u, &bindSparseInfo, VK_NULL_HANDLE));
538     }
539 
540     // Make an image view covering one of the mip levels.
541     const VkImageSubresourceRange viewSubresourceRange = makeImageSubresourceRange(
542         VK_IMAGE_ASPECT_COLOR_BIT, m_testParameters.mipLevel, 1u, m_testParameters.layerNdx, 1u);
543     const Unique<VkImageView> imageView(makeImageView(vk, device, testImage, VK_IMAGE_VIEW_TYPE_2D,
544                                                       m_testParameters.imageFormat, viewSubresourceRange));
545 
546     // resultImage is used in sampler / combined image sampler tests to verify the sampled image.
547     MovePtr<ImageWithMemory> resultImage;
548     VkImageSubresourceRange resultImgSubresourceRange = {};
549     Move<VkImageView> resultImageView;
550     Move<VkSampler> sampler;
551     if (useSampler)
552     {
553         const VkImageCreateInfo resultImageCreateInfo = {
554             VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                         // VkStructureType            sType
555             nullptr,                                                     // const void*                pNext
556             0U,                                                          // VkImageCreateFlags        flags
557             VK_IMAGE_TYPE_2D,                                            // VkImageType                imageType
558             m_testParameters.imageFormat,                                // VkFormat                    format
559             makeExtent3D(testMipLevelSize.x(), testMipLevelSize.y(), 1), // VkExtent3D                extent
560             1u,                                                          // uint32_t                    mipLevels
561             1u,                                                          // uint32_t                    arrayLayers
562             VK_SAMPLE_COUNT_1_BIT,                                       // VkSampleCountFlagBits    samples
563             VK_IMAGE_TILING_OPTIMAL,                                     // VkImageTiling            tiling
564             VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
565                 VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags        usage
566             VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode            sharingMode
567             0u,                                  // uint32_t                    queueFamilyIndexCount
568             nullptr,                             // const uint32_t*            pQueueFamilyIndices
569             VK_IMAGE_LAYOUT_UNDEFINED,           // VkImageLayout            initialLayout
570         };
571 
572         resultImage = MovePtr<ImageWithMemory>(
573             new ImageWithMemory(vk, device, allocator, resultImageCreateInfo, MemoryRequirement::Any));
574         resultImgSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
575         resultImageView = makeImageView(vk, device, **resultImage, VK_IMAGE_VIEW_TYPE_2D, m_testParameters.imageFormat,
576                                         resultImgSubresourceRange);
577 
578         const VkSamplerCreateInfo samplerCreateInfo = {
579             VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,   // VkStructureType            sType
580             nullptr,                                 // const void*                pNext
581             (VkSamplerCreateFlags)0,                 // VkSamplerCreateFlags        flags
582             VK_FILTER_NEAREST,                       // VkFilter                    magFilter
583             VK_FILTER_NEAREST,                       // VkFilter                    minFilter
584             VK_SAMPLER_MIPMAP_MODE_NEAREST,          // VkSamplerMipmapMode        mipmapMode
585             VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,   // VkSamplerAddressMode        addressModeU
586             VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,   // VkSamplerAddressMode        addressModeV
587             VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,   // VkSamplerAddressMode        addressModeW
588             0.0f,                                    // float                    mipLodBias
589             VK_FALSE,                                // VkBool32                    anisotropyEnable
590             1.0f,                                    // float                    maxAnisotropy
591             VK_FALSE,                                // VkBool32                    compareEnable
592             VK_COMPARE_OP_ALWAYS,                    // VkCompareOp                compareOp
593             0.0f,                                    // float                    minLod
594             1.0f,                                    // float                    maxLod
595             VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, // VkBorderColor            borderColor
596             VK_FALSE,                                // VkBool32                    unnormalizedCoordinates
597         };
598         sampler = createSampler(vk, device, &samplerCreateInfo);
599     }
600 
601     // Create the descriptor set.
602     DescriptorSetLayoutBuilder descriptorSetLayoutBuilder;
603     DescriptorPoolBuilder descriptorPoolBuilder;
604 
605     VkShaderStageFlags shaderStage =
606         m_testParameters.testType == Compute ? VK_SHADER_STAGE_COMPUTE_BIT : VK_SHADER_STAGE_FRAGMENT_BIT;
607     VkPipelineStageFlags pipelineStage = m_testParameters.testType == Compute ? VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT :
608                                                                                 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
609     switch (m_testParameters.imageType)
610     {
611     case StorageImage:
612         descriptorSetLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, shaderStage);
613         descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);
614         break;
615     case Sampler:
616         descriptorSetLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, shaderStage);
617         descriptorSetLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_SAMPLER, shaderStage);
618         descriptorSetLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, shaderStage);
619         descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE);
620         descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_SAMPLER);
621         descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);
622         break;
623     case CombinedImageSampler:
624         descriptorSetLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, shaderStage);
625         descriptorSetLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, shaderStage);
626         descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
627         descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);
628         break;
629     default:
630         TCU_THROW(InternalError, "Unimplemented testImage type.");
631     }
632 
633     // Prepare the command buffer.
634     const Unique<VkCommandPool> cmdPool(makeCommandPool(vk, device, queueFamilyIndex));
635     const Unique<VkCommandBuffer> cmdBuffer(
636         allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
637 
638     // Start recording commands.
639     beginCommandBuffer(vk, *cmdBuffer);
640 
641     if (useSampler)
642     {
643         // Clear the result image.
644         const VkImageMemoryBarrier preImageBarrier = {
645             VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
646             nullptr,                                // const void* pNext;
647             0u,                                     // VkAccessFlags srcAccessMask;
648             VK_ACCESS_TRANSFER_WRITE_BIT,           // VkAccessFlags dstAccessMask;
649             VK_IMAGE_LAYOUT_UNDEFINED,              // VkImageLayout oldLayout;
650             VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,   // VkImageLayout newLayout;
651             queueFamilyIndex,                       // uint32_t srcQueueFamilyIndex;
652             queueFamilyIndex,                       // uint32_t dstQueueFamilyIndex;
653             **resultImage,                          // VkImage image;
654             resultImgSubresourceRange               // VkImageSubresourceRange subresourceRange;
655         };
656         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
657                               (VkDependencyFlags)0, 0, nullptr, 0, nullptr, 1, &preImageBarrier);
658 
659         const VkClearColorValue clearColor = makeClearValueColor(tcu::Vec4(0, 0, 0, 1)).color;
660         vk.cmdClearColorImage(*cmdBuffer, **resultImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColor, 1,
661                               &resultImgSubresourceRange);
662 
663         const VkImageMemoryBarrier postImageBarrier = {
664             VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
665             nullptr,                                // const void* pNext;
666             VK_ACCESS_TRANSFER_WRITE_BIT,           // VkAccessFlags srcAccessMask;
667             VK_ACCESS_SHADER_WRITE_BIT,             // VkAccessFlags dstAccessMask;
668             VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,   // VkImageLayout oldLayout;
669             VK_IMAGE_LAYOUT_GENERAL,                // VkImageLayout newLayout;
670             queueFamilyIndex,                       // uint32_t srcQueueFamilyIndex;
671             queueFamilyIndex,                       // uint32_t dstQueueFamilyIndex;
672             **resultImage,                          // VkImage image;
673             resultImgSubresourceRange               // VkImageSubresourceRange subresourceRange;
674         };
675         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, pipelineStage, (VkDependencyFlags)0, 0,
676                               nullptr, 0, nullptr, 1, &postImageBarrier);
677     }
678     else
679     {
680         const auto singleMipSRR = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
681         const auto allMipsSRR   = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, mipLevelCount, 0u, 1u);
682 
683         // Clear the test image.
684         const VkImageMemoryBarrier preImageBarrier = {
685             VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
686             nullptr,                                // const void* pNext;
687             0u,                                     // VkAccessFlags srcAccessMask;
688             VK_ACCESS_TRANSFER_WRITE_BIT,           // VkAccessFlags dstAccessMask;
689             VK_IMAGE_LAYOUT_UNDEFINED,              // VkImageLayout oldLayout;
690             VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,   // VkImageLayout newLayout;
691             queueFamilyIndex,                       // uint32_t srcQueueFamilyIndex;
692             queueFamilyIndex,                       // uint32_t dstQueueFamilyIndex;
693             testImage,                              // VkImage image;
694             allMipsSRR,                             // VkImageSubresourceRange subresourceRange;
695         };
696         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
697                               (VkDependencyFlags)0, 0, nullptr, 0, nullptr, 1, &preImageBarrier);
698 
699         const VkClearColorValue clearColor = makeClearValueColor(tcu::Vec4(0, 0, 0, 1)).color;
700         vk.cmdClearColorImage(*cmdBuffer, testImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColor, 1,
701                               &singleMipSRR);
702 
703         const VkImageMemoryBarrier postImageBarrier = {
704             VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
705             nullptr,                                // const void* pNext;
706             VK_ACCESS_TRANSFER_WRITE_BIT,           // VkAccessFlags srcAccessMask;
707             VK_ACCESS_SHADER_WRITE_BIT,             // VkAccessFlags dstAccessMask;
708             VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,   // VkImageLayout oldLayout;
709             VK_IMAGE_LAYOUT_GENERAL,                // VkImageLayout newLayout;
710             queueFamilyIndex,                       // uint32_t srcQueueFamilyIndex;
711             queueFamilyIndex,                       // uint32_t dstQueueFamilyIndex;
712             testImage,                              // VkImage image;
713             allMipsSRR,                             // VkImageSubresourceRange subresourceRange;
714         };
715         vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, pipelineStage, (VkDependencyFlags)0, 0,
716                               nullptr, 0, nullptr, 1, &postImageBarrier);
717     }
718 
719     if (useSampler)
720     {
721         // Copy the input image to the target mip level.
722         std::vector<VkBufferImageCopy> copies;
723         copies.push_back(makeBufferImageCopy(
724             makeExtent3D(testMipLevelSize),
725             makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, m_testParameters.mipLevel, 0, 1)));
726         copyBufferToImage(vk, *cmdBuffer, **inputImageBuffer, bufferSize, copies, VK_IMAGE_ASPECT_COLOR_BIT,
727                           mipLevelCount, 1u, testImage, VK_IMAGE_LAYOUT_GENERAL, pipelineStage);
728     }
729 
730     const Move<VkDescriptorSetLayout> descriptorSetLayout(descriptorSetLayoutBuilder.build(vk, device));
731     const Move<VkDescriptorPool> descriptorPool(
732         descriptorPoolBuilder.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
733     const Unique<VkDescriptorSet> descriptorSet(makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
734     const VkDescriptorImageInfo testImageDescriptorInfo =
735         makeDescriptorImageInfo(*sampler, *imageView, VK_IMAGE_LAYOUT_GENERAL);
736 
737     // Write descriptor update.
738     {
739         DescriptorSetUpdateBuilder descriptorSetUpdateBuilder;
740         uint32_t bindingIdx = 0;
741 
742         switch (m_testParameters.imageType)
743         {
744         case StorageImage:
745             descriptorSetUpdateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
746                                                    VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &testImageDescriptorInfo);
747             break;
748         case Sampler:
749             descriptorSetUpdateBuilder.writeSingle(*descriptorSet,
750                                                    DescriptorSetUpdateBuilder::Location::binding(bindingIdx++),
751                                                    VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, &testImageDescriptorInfo);
752             descriptorSetUpdateBuilder.writeSingle(*descriptorSet,
753                                                    DescriptorSetUpdateBuilder::Location::binding(bindingIdx++),
754                                                    VK_DESCRIPTOR_TYPE_SAMPLER, &testImageDescriptorInfo);
755             break;
756         case CombinedImageSampler:
757             descriptorSetUpdateBuilder.writeSingle(*descriptorSet,
758                                                    DescriptorSetUpdateBuilder::Location::binding(bindingIdx++),
759                                                    VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &testImageDescriptorInfo);
760             break;
761         }
762 
763         if (useSampler)
764         {
765             const VkDescriptorImageInfo resultImageDescriptorInfo =
766                 makeDescriptorImageInfo(VK_NULL_HANDLE, *resultImageView, VK_IMAGE_LAYOUT_GENERAL);
767             descriptorSetUpdateBuilder.writeSingle(*descriptorSet,
768                                                    DescriptorSetUpdateBuilder::Location::binding(bindingIdx),
769                                                    VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &resultImageDescriptorInfo);
770         }
771 
772         descriptorSetUpdateBuilder.update(vk, device);
773     }
774 
775     const VkSemaphore *sparseImageSemaphorePtr = (useSparseBinding ? &sparseImageSemaphore.get() : nullptr);
776 
777     if (m_testParameters.testType == Compute)
778         runComputePipeline(*descriptorSet, *descriptorSetLayout, testMipLevelSize, *cmdBuffer,
779                            useSampler ? **resultImage : testImage, *outputBuffer, sparseImageSemaphorePtr);
780     else
781         runGraphicsPipeline(*descriptorSet, *descriptorSetLayout, testMipLevelSize, *cmdBuffer,
782                             useSampler ? **resultImage : testImage, *outputBuffer, sparseImageSemaphorePtr);
783 
784     // Validate the results.
785     {
786         // Create a reference image.
787         // 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.
788         tcu::TextureLevel referenceImage(textureFormat, testMipLevelSize.x(), testMipLevelSize.y(), 1u);
789         fillImage(referenceImage.getAccess(), 0u);
790 
791         const Allocation &outputBufferAllocation = outputBuffer.getAllocation();
792         invalidateAlloc(vk, device, outputBufferAllocation);
793 
794         const uint32_t *bufferPtr = static_cast<uint32_t *>(outputBufferAllocation.getHostPtr());
795         tcu::ConstPixelBufferAccess pixelBufferAccess(mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM), testMipLevelSize.x(),
796                                                       testMipLevelSize.y(), 1u, bufferPtr);
797 
798         if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Result", "Result comparison",
799                                         referenceImage, pixelBufferAccess, tcu::Vec4(0.01f), tcu::COMPARE_LOG_ON_ERROR))
800             return tcu::TestStatus::fail("Pixel comparison failed.");
801     }
802 
803     return tcu::TestStatus::pass("pass");
804 }
805 
806 class ComputeImage2DView3DImageTest : public vkt::TestCase
807 {
808 public:
ComputeImage2DView3DImageTest(tcu::TestContext & testContext,const char * name,const TestParameters & testParameters)809     ComputeImage2DView3DImageTest(tcu::TestContext &testContext, const char *name, const TestParameters &testParameters)
810         : vkt::TestCase(testContext, name)
811         , m_testParameters(testParameters)
812     {
813     }
~ComputeImage2DView3DImageTest(void)814     virtual ~ComputeImage2DView3DImageTest(void)
815     {
816     }
817 
818     virtual void initPrograms(SourceCollections &sourceCollections) const;
819     virtual void checkSupport(Context &context) const;
820     virtual TestInstance *createInstance(Context &context) const;
821 
822 private:
823     const TestParameters m_testParameters;
824 };
825 
checkSupport(Context & context) const826 void ComputeImage2DView3DImageTest::checkSupport(Context &context) const
827 {
828     DE_ASSERT(m_testParameters.pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC);
829 
830     if (!context.isDeviceFunctionalitySupported("VK_EXT_image_2d_view_of_3d"))
831         TCU_THROW(NotSupportedError, "VK_EXT_image_2d_view_of_3d functionality not supported.");
832 
833     if (!context.getImage2DViewOf3DFeaturesEXT().image2DViewOf3D)
834         TCU_THROW(NotSupportedError, "image2DViewOf3D not supported.");
835 
836     if (m_testParameters.imageType != StorageImage && !context.getImage2DViewOf3DFeaturesEXT().sampler2DViewOf3D)
837         TCU_THROW(NotSupportedError, "sampler2DViewOf3D not supported.");
838 
839     if (m_testParameters.imageBindingType == Sparse)
840         context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SPARSE_BINDING);
841 }
842 
initPrograms(SourceCollections & sourceCollections) const843 void ComputeImage2DView3DImageTest::initPrograms(SourceCollections &sourceCollections) const
844 {
845     std::ostringstream src;
846     tcu::IVec3 mipLevelSize = computeMipLevelSize(m_testParameters.imageSize, m_testParameters.mipLevel);
847     if (m_testParameters.imageType == StorageImage)
848     {
849         src << "#version 450 core\n"
850             << "layout (local_size_x = 1, local_size_y = 1) in;\n"
851             << "layout (binding = 0, rgba8) writeonly uniform highp image2D storageImage;\n"
852             << "void main (void) {\n"
853             << "    ivec2 uv = ivec2(gl_GlobalInvocationID.xy);\n"
854             << "    float c = float((uv.x + uv.y) & 1);\n"
855             << "    vec4 color = vec4(c, c, c, 1.0);\n"
856             << "    imageStore(storageImage, uv, color);\n"
857             << "}\n";
858     }
859     else if (m_testParameters.imageType == Sampler)
860     {
861         src << "#version 450 core\n"
862             << "layout (local_size_x = 1, local_size_y = 1) in;\n"
863             << "layout (set=0, binding = 0) uniform texture2D image;\n"
864             << "layout (set=0, binding = 1) uniform sampler samp;\n"
865             << "layout (rgba8, set=0, binding = 2) writeonly uniform highp image2D verifyImage;\n"
866             << "void main (void) {\n"
867             << "    ivec2 uv = ivec2(gl_GlobalInvocationID.xy);\n"
868             << "    vec2 texCoord = vec2(gl_GlobalInvocationID.xy) / " << mipLevelSize.x() << ".0;\n"
869             << "    vec4 color = texture(sampler2D(image, samp), texCoord);\n"
870             << "    imageStore(verifyImage, uv, color);\n"
871             << "}\n";
872     }
873     else if (m_testParameters.imageType == CombinedImageSampler)
874     {
875         src << "#version 450 core\n"
876             << "layout (local_size_x = 1, local_size_y = 1) in;\n"
877             << "layout (binding = 0) uniform sampler2D combinedSampler;\n"
878             << "layout (rgba8, set=0, binding=1) writeonly uniform highp image2D verifyImage;\n"
879             << "void main (void) {\n"
880             << "    ivec2 uv = ivec2(gl_GlobalInvocationID.xy);\n"
881             << "    vec2 texCoord = vec2(gl_GlobalInvocationID.xy) / " << mipLevelSize.x() << ".0;\n"
882             << "    vec4 color = texture(combinedSampler, texCoord);\n"
883             << "    imageStore(verifyImage, uv, color);\n"
884             << "}\n";
885     }
886 
887     sourceCollections.glslSources.add("comp") << glu::ComputeSource(src.str());
888 }
889 
createInstance(Context & context) const890 TestInstance *ComputeImage2DView3DImageTest::createInstance(Context &context) const
891 {
892     return new Image2DView3DImageInstance(context, m_testParameters);
893 }
894 
895 class FragmentImage2DView3DImageTest : public vkt::TestCase
896 {
897 public:
FragmentImage2DView3DImageTest(tcu::TestContext & testContext,const char * name,const TestParameters & testParameters)898     FragmentImage2DView3DImageTest(tcu::TestContext &testContext, const char *name,
899                                    const TestParameters &testParameters)
900         : vkt::TestCase(testContext, name)
901         , m_testParameters(testParameters)
902     {
903     }
~FragmentImage2DView3DImageTest(void)904     virtual ~FragmentImage2DView3DImageTest(void)
905     {
906     }
907 
908     virtual void initPrograms(SourceCollections &sourceCollections) const;
909     virtual void checkSupport(Context &context) const;
910     virtual TestInstance *createInstance(Context &context) const;
911 
912 private:
913     const TestParameters m_testParameters;
914 };
915 
initPrograms(SourceCollections & sourceCollections) const916 void FragmentImage2DView3DImageTest::initPrograms(SourceCollections &sourceCollections) const
917 {
918     std::stringstream vertShader;
919     vertShader << "#version 450 core\n"
920                << "layout(location = 0) in vec4 in_position;\n"
921                << "out gl_PerVertex {\n"
922                << "    vec4  gl_Position;\n"
923                << "    float gl_PointSize;\n"
924                << "};\n"
925                << "void main() {\n"
926                << "    gl_PointSize = 1.0;\n"
927                << "    gl_Position  = in_position;\n"
928                << "}\n";
929     sourceCollections.glslSources.add("vert") << glu::VertexSource(vertShader.str());
930 
931     tcu::IVec3 mipLevelSize = computeMipLevelSize(m_testParameters.imageSize, m_testParameters.mipLevel);
932     std::stringstream fragShader;
933     if (m_testParameters.imageType == StorageImage)
934     {
935         fragShader << "#version 450 core\n"
936                    << "layout(rgba8, set = 0, binding = 0) uniform image2D storageImage;\n"
937                    << "void main()\n"
938                    << "{\n"
939                    << "    ivec2 uv = ivec2(gl_FragCoord.xy);\n"
940                    << "    float c = float((uv.x + uv.y) & 1);\n"
941                    << "    vec4 color = vec4(c, c, c, 1.0);\n"
942                    << "    imageStore(storageImage, uv, color);\n"
943                    << "}\n";
944     }
945 
946     else if (m_testParameters.imageType == Sampler)
947     {
948         fragShader << "#version 450 core\n"
949                    << "layout (set = 0, binding = 0) uniform texture2D image;\n"
950                    << "layout (set = 0, binding = 1) uniform sampler samp;\n"
951                    << "layout (rgba8, set = 0, binding = 2) uniform image2D verifyImage;\n"
952                    << "void main (void) {\n"
953                    << "    ivec2 uv = ivec2(gl_FragCoord.xy);\n"
954                    << "    vec2 texCoord = gl_FragCoord.xy / " << mipLevelSize.x() << ".0;\n"
955                    << "    vec4 color = texture(sampler2D(image, samp), texCoord);\n"
956                    << "    imageStore(verifyImage, uv, color);\n"
957                    << "}\n";
958     }
959     else if (m_testParameters.imageType == CombinedImageSampler)
960     {
961         fragShader << "#version 450 core\n"
962                    << "layout (set = 0, binding = 0) uniform sampler2D combinedSampler;\n"
963                    << "layout (rgba8, set = 0, binding = 1) uniform image2D verifyImage;\n"
964                    << "void main (void) {\n"
965                    << "    ivec2 uv = ivec2(gl_FragCoord.xy);\n"
966                    << "    vec2 texCoord = gl_FragCoord.xy / " << mipLevelSize.x() << ".0;\n"
967                    << "    vec4 color = texture(combinedSampler, texCoord);\n"
968                    << "    imageStore(verifyImage, uv, color);\n"
969                    << "}\n";
970     }
971     sourceCollections.glslSources.add("frag") << glu::FragmentSource(fragShader.str());
972 }
973 
checkSupport(Context & context) const974 void FragmentImage2DView3DImageTest::checkSupport(Context &context) const
975 {
976     checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(),
977                                           m_testParameters.pipelineConstructionType);
978 
979     if (!context.isDeviceFunctionalitySupported("VK_EXT_image_2d_view_of_3d"))
980         TCU_THROW(NotSupportedError, "VK_EXT_image_2d_view_of_3d functionality not supported.");
981 
982     if (!context.getImage2DViewOf3DFeaturesEXT().image2DViewOf3D)
983         TCU_THROW(NotSupportedError, "image2DViewOf3D not supported.");
984 
985     if (m_testParameters.imageType != StorageImage && !context.getImage2DViewOf3DFeaturesEXT().sampler2DViewOf3D)
986         TCU_THROW(NotSupportedError, "texture2DViewOf3D not supported.");
987 
988     if (!context.getDeviceFeatures().fragmentStoresAndAtomics)
989         TCU_THROW(NotSupportedError, "fragmentStoresAndAtomics not supported");
990 
991     if (m_testParameters.imageBindingType == Sparse)
992         context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SPARSE_BINDING);
993 }
994 
createInstance(Context & context) const995 TestInstance *FragmentImage2DView3DImageTest::createInstance(Context &context) const
996 {
997     return new Image2DView3DImageInstance(context, m_testParameters);
998 }
999 
1000 } // namespace
1001 
createImage2DViewOf3DTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType)1002 tcu::TestCaseGroup *createImage2DViewOf3DTests(tcu::TestContext &testCtx,
1003                                                PipelineConstructionType pipelineConstructionType)
1004 {
1005     de::MovePtr<tcu::TestCaseGroup> imageTests(new tcu::TestCaseGroup(testCtx, "image_2d_view_3d_image"));
1006     de::MovePtr<tcu::TestCaseGroup> computeGroup(new tcu::TestCaseGroup(testCtx, "compute"));
1007     de::MovePtr<tcu::TestCaseGroup> fragmentGroup(new tcu::TestCaseGroup(testCtx, "fragment"));
1008 
1009     const struct
1010     {
1011         const ImageAccessType imageType;
1012         const std::string name;
1013     } imageAccessTypes[]{
1014         {StorageImage, "storage"}, {Sampler, "sampler"}, {CombinedImageSampler, "combined_image_sampler"}};
1015 
1016     const int32_t imageDimension = 64;
1017     for (const auto &imageAccessType : imageAccessTypes)
1018     {
1019         de::MovePtr<tcu::TestCaseGroup> computeSubGroup(new tcu::TestCaseGroup(testCtx, imageAccessType.name.c_str()));
1020         de::MovePtr<tcu::TestCaseGroup> fragmentSubGroup(new tcu::TestCaseGroup(testCtx, imageAccessType.name.c_str()));
1021         for (uint32_t mipLevel = 0; mipLevel < 3; mipLevel += 2)
1022         {
1023             // Test the first and the last layer of the mip level.
1024             std::vector<int32_t> layers = {0, computeMipLevelDimension(imageDimension, mipLevel) - 1};
1025             for (const auto &layer : layers)
1026             {
1027                 for (const auto &imageBindingType : {ImageBindingType::Normal, ImageBindingType::Sparse})
1028                 {
1029                     TestParameters testParameters{
1030                         tcu::IVec3(imageDimension), // IVec3                        imageSize
1031                         mipLevel,                   // uint32_t                        mipLevel
1032                         layer,                      // int32_t                        layerNdx
1033                         imageAccessType.imageType,  // ImageAccessType                imageType
1034                         Fragment,                   // TestType                        testType
1035                         VK_FORMAT_R8G8B8A8_UNORM,   // VkFormat                        imageFormat
1036                         pipelineConstructionType,   // PipelineConstructionType        pipelineConstructionType
1037                         imageBindingType            // ImageBindingType             imageBindingType
1038                     };
1039                     std::string testName = "mip" + std::to_string(mipLevel) + "_layer" + std::to_string(layer) +
1040                                            (imageBindingType == Sparse ? "_sparse" : "");
1041                     fragmentSubGroup->addChild(
1042                         new FragmentImage2DView3DImageTest(testCtx, testName.c_str(), testParameters));
1043 
1044                     if (pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
1045                     {
1046                         testParameters.testType = Compute;
1047                         computeSubGroup->addChild(
1048                             new ComputeImage2DView3DImageTest(testCtx, testName.c_str(), testParameters));
1049                     }
1050                 }
1051             }
1052         }
1053         computeGroup->addChild(computeSubGroup.release());
1054         fragmentGroup->addChild(fragmentSubGroup.release());
1055     }
1056 
1057     imageTests->addChild(computeGroup.release());
1058     imageTests->addChild(fragmentGroup.release());
1059     return imageTests.release();
1060 }
1061 
1062 } // namespace pipeline
1063 } // namespace vkt
1064