xref: /aosp_15_r20/external/deqp/external/vulkancts/modules/vulkan/image/vktImageSizeTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2016 The Khronos Group Inc.
6  * Copyright (c) 2016 The Android Open Source Project
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21  * \file
22  * \brief Image size Tests
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktImageSizeTests.hpp"
26 #include "vktTestCaseUtil.hpp"
27 #include "vktImageTestsUtil.hpp"
28 #include "vktImageTexture.hpp"
29 
30 #include "vkDefs.hpp"
31 #include "vkRef.hpp"
32 #include "vkRefUtil.hpp"
33 #include "vkPlatform.hpp"
34 #include "vkPrograms.hpp"
35 #include "vkMemUtil.hpp"
36 #include "vkBarrierUtil.hpp"
37 #include "vkBuilderUtil.hpp"
38 #include "vkImageUtil.hpp"
39 #include "vkCmdUtil.hpp"
40 #include "vkObjUtil.hpp"
41 #include "vkBufferWithMemory.hpp"
42 
43 #include "deUniquePtr.hpp"
44 #include "deStringUtil.hpp"
45 
46 #include <string>
47 
48 using namespace vk;
49 
50 namespace vkt
51 {
52 namespace image
53 {
54 namespace
55 {
56 
57 //! Get a texture based on image type and suggested size.
getTexture(const ImageType imageType,const tcu::IVec3 & size)58 Texture getTexture(const ImageType imageType, const tcu::IVec3 &size)
59 {
60     switch (imageType)
61     {
62     case IMAGE_TYPE_1D:
63     case IMAGE_TYPE_BUFFER:
64         return Texture(imageType, tcu::IVec3(size.x(), 1, 1), 1);
65 
66     case IMAGE_TYPE_1D_ARRAY:
67         return Texture(imageType, tcu::IVec3(size.x(), 1, 1), size.y());
68 
69     case IMAGE_TYPE_2D:
70         return Texture(imageType, tcu::IVec3(size.x(), size.y(), 1), 1);
71 
72     case IMAGE_TYPE_2D_ARRAY:
73         return Texture(imageType, tcu::IVec3(size.x(), size.y(), 1), size.z());
74 
75     case IMAGE_TYPE_CUBE:
76         return Texture(imageType, tcu::IVec3(size.x(), size.x(), 1), 6);
77 
78     case IMAGE_TYPE_CUBE_ARRAY:
79         return Texture(imageType, tcu::IVec3(size.x(), size.x(), 1), 2 * 6);
80 
81     case IMAGE_TYPE_3D:
82         return Texture(imageType, size, 1);
83 
84     default:
85         DE_FATAL("Internal error");
86         return Texture(IMAGE_TYPE_LAST, tcu::IVec3(), 0);
87     }
88 }
89 
makeImageCreateInfo(const Texture & texture,const VkFormat format,const bool is2DViewOf3D)90 inline VkImageCreateInfo makeImageCreateInfo(const Texture &texture, const VkFormat format, const bool is2DViewOf3D)
91 {
92     VkImageViewCreateFlags createFlags = 0u;
93 
94     if (isCube(texture))
95         createFlags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
96 #ifndef CTS_USES_VULKANSC
97     else if (is2DViewOf3D)
98         createFlags |= VK_IMAGE_CREATE_2D_VIEW_COMPATIBLE_BIT_EXT;
99 #else
100     DE_UNREF(is2DViewOf3D);
101 #endif // CTS_USES_VULKANSC
102 
103     const VkImageCreateInfo imageParams = {
104         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
105         DE_NULL,                             // const void* pNext;
106         createFlags,                         // VkImageCreateFlags flags;
107         mapImageType(texture.type()),        // VkImageType imageType;
108         format,                              // VkFormat format;
109         makeExtent3D(texture.layerSize()),   // VkExtent3D extent;
110         1u,                                  // uint32_t mipLevels;
111         (uint32_t)texture.numLayers(),       // uint32_t arrayLayers;
112         VK_SAMPLE_COUNT_1_BIT,               // VkSampleCountFlagBits samples;
113         VK_IMAGE_TILING_OPTIMAL,             // VkImageTiling tiling;
114         VK_IMAGE_USAGE_STORAGE_BIT,          // VkImageUsageFlags usage;
115         VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode sharingMode;
116         0u,                                  // uint32_t queueFamilyIndexCount;
117         DE_NULL,                             // const uint32_t* pQueueFamilyIndices;
118         VK_IMAGE_LAYOUT_UNDEFINED,           // VkImageLayout initialLayout;
119     };
120     return imageParams;
121 }
122 
123 //! Interpret the memory as IVec3
readIVec3(const void * const data)124 inline tcu::IVec3 readIVec3(const void *const data)
125 {
126     const int *const p = reinterpret_cast<const int *>(data);
127     return tcu::IVec3(p[0], p[1], p[2]);
128 }
129 
getExpectedImageSizeResult(const Texture & texture,const bool is2DViewOf3D)130 tcu::IVec3 getExpectedImageSizeResult(const Texture &texture, const bool is2DViewOf3D)
131 {
132     // GLSL imageSize() function returns:
133     // z = 0 for cubes
134     // z = N for cube arrays, where N is the number of cubes
135     // y or z = L where L is the number of layers for other array types (e.g. 1D array, 2D array)
136     // z = D where D is the depth of 3d image
137 
138     const tcu::IVec3 size  = texture.size();
139     const int numCubeFaces = 6;
140 
141     switch (texture.type())
142     {
143     case IMAGE_TYPE_1D:
144     case IMAGE_TYPE_BUFFER:
145         return tcu::IVec3(size.x(), 0, 0);
146 
147     case IMAGE_TYPE_1D_ARRAY:
148     case IMAGE_TYPE_2D:
149     case IMAGE_TYPE_CUBE:
150         return tcu::IVec3(size.x(), size.y(), 0);
151 
152     case IMAGE_TYPE_2D_ARRAY:
153     case IMAGE_TYPE_3D:
154     {
155         if (is2DViewOf3D)
156             return tcu::IVec3(size.x(), size.y(), 0);
157         return size;
158     }
159 
160     case IMAGE_TYPE_CUBE_ARRAY:
161         return tcu::IVec3(size.x(), size.y(), size.z() / numCubeFaces);
162 
163     default:
164         DE_FATAL("Internal error");
165         return tcu::IVec3();
166     }
167 }
168 
169 class SizeTest : public TestCase
170 {
171 public:
172     enum TestFlags
173     {
174         FLAG_READONLY_IMAGE  = 1u << 0,
175         FLAG_WRITEONLY_IMAGE = 1u << 1,
176     };
177 
178     SizeTest(tcu::TestContext &testCtx, const std::string &name, const Texture &texture, const VkFormat format,
179              const uint32_t flags, const bool is2DViewOf3D);
180 
181     void initPrograms(SourceCollections &programCollection) const;
182     TestInstance *createInstance(Context &context) const;
183     virtual void checkSupport(Context &context) const;
184 
185 private:
186     const Texture m_texture;
187     const VkFormat m_format;
188     const bool m_useReadonly;
189     const bool m_useWriteonly;
190     const bool m_2DViewOf3D;
191 };
192 
SizeTest(tcu::TestContext & testCtx,const std::string & name,const Texture & texture,const VkFormat format,const uint32_t flags,const bool is2DViewOf3D)193 SizeTest::SizeTest(tcu::TestContext &testCtx, const std::string &name, const Texture &texture, const VkFormat format,
194                    const uint32_t flags, const bool is2DViewOf3D)
195     : TestCase(testCtx, name)
196     , m_texture(texture)
197     , m_format(format)
198     , m_useReadonly((flags & FLAG_READONLY_IMAGE) != 0)
199     , m_useWriteonly((flags & FLAG_WRITEONLY_IMAGE) != 0)
200     , m_2DViewOf3D(is2DViewOf3D)
201 {
202     // We expect at least one flag to be set.
203     DE_ASSERT(m_useReadonly || m_useWriteonly);
204 
205     // For 2D views of 3D we need 3D images.
206     DE_ASSERT(!m_2DViewOf3D || m_texture.type() == IMAGE_TYPE_3D);
207 }
208 
checkSupport(Context & context) const209 void SizeTest::checkSupport(Context &context) const
210 {
211     const auto imgType = m_texture.type();
212 
213     if (imgType == IMAGE_TYPE_CUBE_ARRAY)
214         context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_IMAGE_CUBE_ARRAY);
215 
216     if (imgType != IMAGE_TYPE_BUFFER)
217     {
218         const auto &vki           = context.getInstanceInterface();
219         const auto physicalDevice = context.getPhysicalDevice();
220         const auto createInfo     = makeImageCreateInfo(m_texture, m_format, m_2DViewOf3D);
221         VkImageFormatProperties formatProperties;
222 
223         const auto result = vki.getPhysicalDeviceImageFormatProperties(
224             physicalDevice, createInfo.format, createInfo.imageType, createInfo.tiling, createInfo.usage,
225             createInfo.flags, &formatProperties);
226 
227         if (result == VK_ERROR_FORMAT_NOT_SUPPORTED)
228             TCU_THROW(NotSupportedError, "Format not supported for the specified usage");
229     }
230 
231     if (m_2DViewOf3D)
232         context.requireDeviceFunctionality("VK_EXT_image_2d_view_of_3d");
233 }
234 
initPrograms(SourceCollections & programCollection) const235 void SizeTest::initPrograms(SourceCollections &programCollection) const
236 {
237     const std::string formatQualifierStr = getShaderImageFormatQualifier(mapVkFormat(m_format));
238     const std::string imageTypeStr =
239         getShaderImageType(mapVkFormat(m_format), (m_2DViewOf3D ? IMAGE_TYPE_2D : m_texture.type()));
240     const int dimension = m_texture.dimension();
241 
242     std::ostringstream accessQualifier;
243     if (m_useReadonly)
244         accessQualifier << " readonly";
245     if (m_useWriteonly)
246         accessQualifier << " writeonly";
247 
248     std::ostringstream src;
249     src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
250         << "\n"
251         << "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
252         << "layout (binding = 0, " << formatQualifierStr << ")" << accessQualifier.str() << " uniform highp "
253         << imageTypeStr << " u_image;\n"
254         << "layout (binding = 1) writeonly buffer Output {\n"
255         << "    ivec3 size;\n"
256         << "} sb_out;\n"
257         << "\n"
258         << "void main (void)\n"
259         << "{\n"
260         << (dimension == 1 ? "    sb_out.size = ivec3(imageSize(u_image), 0, 0);\n" :
261             dimension == 2 || m_2DViewOf3D || m_texture.type() == IMAGE_TYPE_CUBE ? // cubes return ivec2
262                 "    sb_out.size = ivec3(imageSize(u_image), 0);\n" :
263                 dimension == 3 ? // cube arrays return ivec3
264                     "    sb_out.size = imageSize(u_image);\n" :
265                     "")
266         << "}\n";
267 
268     programCollection.glslSources.add("comp") << glu::ComputeSource(src.str());
269 }
270 
271 //! Build a case name, e.g. "readonly_writeonly_32x32"
getCaseName(const Texture & texture,const uint32_t flags,const bool is2DViewOf3D)272 std::string getCaseName(const Texture &texture, const uint32_t flags, const bool is2DViewOf3D)
273 {
274     std::ostringstream str;
275     str << ((flags & SizeTest::FLAG_READONLY_IMAGE) != 0 ? "readonly_" : "")
276         << ((flags & SizeTest::FLAG_WRITEONLY_IMAGE) != 0 ? "writeonly_" : "");
277 
278     if (is2DViewOf3D)
279         str << "2d_view_";
280 
281     const int numComponents = texture.dimension();
282     for (int i = 0; i < numComponents; ++i)
283         str << (i == 0 ? "" : "x") << texture.size()[i];
284 
285     return str.str();
286 }
287 
288 //! Base test instance for image and buffer tests
289 class SizeTestInstance : public TestInstance
290 {
291 public:
292     SizeTestInstance(Context &context, const Texture &texture, const VkFormat format, const bool is2DViewOf3D = false);
293 
294     tcu::TestStatus iterate(void);
~SizeTestInstance(void)295     virtual ~SizeTestInstance(void)
296     {
297     }
298 
299 protected:
300     virtual VkDescriptorSetLayout prepareDescriptors(void)             = 0;
301     virtual VkDescriptorSet getDescriptorSet(void) const               = 0;
302     virtual void commandBeforeCompute(const VkCommandBuffer cmdBuffer) = 0;
303 
304     const Texture m_texture;
305     const VkFormat m_format;
306     const VkDeviceSize m_resultBufferSizeBytes;
307     const bool m_2DViewOf3D;
308     de::MovePtr<BufferWithMemory> m_resultBuffer; //!< Shader writes the output here.
309 };
310 
SizeTestInstance(Context & context,const Texture & texture,const VkFormat format,const bool is2DViewOf3D)311 SizeTestInstance::SizeTestInstance(Context &context, const Texture &texture, const VkFormat format,
312                                    const bool is2DViewOf3D)
313     : TestInstance(context)
314     , m_texture(texture)
315     , m_format(format)
316     , m_resultBufferSizeBytes(3 * sizeof(uint32_t)) // ivec3 in shader
317     , m_2DViewOf3D(is2DViewOf3D)
318 {
319     const DeviceInterface &vk = m_context.getDeviceInterface();
320     const VkDevice device     = m_context.getDevice();
321     Allocator &allocator      = m_context.getDefaultAllocator();
322 
323     // Create an SSBO for shader output.
324 
325     m_resultBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(
326         vk, device, allocator, makeBufferCreateInfo(m_resultBufferSizeBytes, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT),
327         MemoryRequirement::HostVisible));
328 }
329 
iterate(void)330 tcu::TestStatus SizeTestInstance::iterate(void)
331 {
332     const DeviceInterface &vk       = m_context.getDeviceInterface();
333     const VkDevice device           = m_context.getDevice();
334     const VkQueue queue             = m_context.getUniversalQueue();
335     const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
336 
337     // Create memory barriers.
338 
339     const VkBufferMemoryBarrier shaderWriteBarrier = makeBufferMemoryBarrier(
340         VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, m_resultBuffer->get(), 0ull, m_resultBufferSizeBytes);
341 
342     // Create the pipeline.
343 
344     const Unique<VkShaderModule> shaderModule(
345         createShaderModule(vk, device, m_context.getBinaryCollection().get("comp"), 0));
346 
347     const VkDescriptorSetLayout descriptorSetLayout = prepareDescriptors();
348     const VkDescriptorSet descriptorSet             = getDescriptorSet();
349 
350     const Unique<VkPipelineLayout> pipelineLayout(makePipelineLayout(vk, device, descriptorSetLayout));
351     const Unique<VkPipeline> pipeline(makeComputePipeline(vk, device, *pipelineLayout, *shaderModule));
352 
353     const Unique<VkCommandPool> cmdPool(
354         createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
355     const Unique<VkCommandBuffer> cmdBuffer(
356         allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
357 
358     beginCommandBuffer(vk, *cmdBuffer);
359 
360     vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
361     vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &descriptorSet, 0u,
362                              DE_NULL);
363 
364     commandBeforeCompute(*cmdBuffer);
365     vk.cmdDispatch(*cmdBuffer, 1, 1, 1);
366     vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
367                           (VkDependencyFlags)0, 0, (const VkMemoryBarrier *)DE_NULL, 1, &shaderWriteBarrier, 0,
368                           (const VkImageMemoryBarrier *)DE_NULL);
369 
370     endCommandBuffer(vk, *cmdBuffer);
371 
372     submitCommandsAndWait(vk, device, queue, *cmdBuffer);
373 
374     // Compare the result.
375 
376     const Allocation &bufferAlloc = m_resultBuffer->getAllocation();
377     invalidateAlloc(vk, device, bufferAlloc);
378 
379     const tcu::IVec3 resultSize   = readIVec3(bufferAlloc.getHostPtr());
380     const tcu::IVec3 expectedSize = getExpectedImageSizeResult(m_texture, m_2DViewOf3D);
381 
382     if (resultSize != expectedSize)
383         return tcu::TestStatus::fail("Incorrect imageSize(): expected " + de::toString(expectedSize) + " but got " +
384                                      de::toString(resultSize));
385     else
386         return tcu::TestStatus::pass("Passed");
387 }
388 
389 class ImageSizeTestInstance : public SizeTestInstance
390 {
391 public:
392     ImageSizeTestInstance(Context &context, const Texture &texture, const VkFormat format, const bool is2DViewOf3D);
393 
394 protected:
395     VkDescriptorSetLayout prepareDescriptors(void);
396     void commandBeforeCompute(const VkCommandBuffer cmdBuffer);
397 
getDescriptorSet(void) const398     VkDescriptorSet getDescriptorSet(void) const
399     {
400         return *m_descriptorSet;
401     }
402 
403     de::MovePtr<Image> m_image;
404     Move<VkImageView> m_imageView;
405     Move<VkDescriptorSetLayout> m_descriptorSetLayout;
406     Move<VkDescriptorPool> m_descriptorPool;
407     Move<VkDescriptorSet> m_descriptorSet;
408 };
409 
ImageSizeTestInstance(Context & context,const Texture & texture,const VkFormat format,const bool is2DViewOf3D)410 ImageSizeTestInstance::ImageSizeTestInstance(Context &context, const Texture &texture, const VkFormat format,
411                                              const bool is2DViewOf3D)
412     : SizeTestInstance(context, texture, format, is2DViewOf3D)
413 {
414     const DeviceInterface &vk = m_context.getDeviceInterface();
415     const VkDevice device     = m_context.getDevice();
416     Allocator &allocator      = m_context.getDefaultAllocator();
417 
418     // Create an image. Its data will be uninitialized, as we're not reading from it.
419 
420     m_image = de::MovePtr<Image>(new Image(
421         vk, device, allocator, makeImageCreateInfo(m_texture, m_format, m_2DViewOf3D), MemoryRequirement::Any));
422 
423     const auto baseLayer = (m_2DViewOf3D ? static_cast<uint32_t>(m_texture.size().z() / 2) : 0u);
424     const auto viewType  = (m_2DViewOf3D ? VK_IMAGE_VIEW_TYPE_2D : mapImageViewType(m_texture.type()));
425     const auto subresourceRange =
426         makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, baseLayer, m_texture.numLayers());
427 
428     m_imageView = makeImageView(vk, device, m_image->get(), viewType, m_format, subresourceRange);
429 }
430 
prepareDescriptors(void)431 VkDescriptorSetLayout ImageSizeTestInstance::prepareDescriptors(void)
432 {
433     const DeviceInterface &vk = m_context.getDeviceInterface();
434     const VkDevice device     = m_context.getDevice();
435 
436     m_descriptorSetLayout = DescriptorSetLayoutBuilder()
437                                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
438                                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
439                                 .build(vk, device);
440 
441     m_descriptorPool = DescriptorPoolBuilder()
442                            .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
443                            .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
444                            .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
445 
446     m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
447 
448     const VkDescriptorImageInfo descriptorImageInfo =
449         makeDescriptorImageInfo(DE_NULL, *m_imageView, VK_IMAGE_LAYOUT_GENERAL);
450     const VkDescriptorBufferInfo descriptorBufferInfo =
451         makeDescriptorBufferInfo(m_resultBuffer->get(), 0ull, m_resultBufferSizeBytes);
452 
453     DescriptorSetUpdateBuilder()
454         .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
455                      VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
456         .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u),
457                      VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorBufferInfo)
458         .update(vk, device);
459 
460     return *m_descriptorSetLayout;
461 }
462 
commandBeforeCompute(const VkCommandBuffer cmdBuffer)463 void ImageSizeTestInstance::commandBeforeCompute(const VkCommandBuffer cmdBuffer)
464 {
465     const DeviceInterface &vk = m_context.getDeviceInterface();
466 
467     const VkImageSubresourceRange subresourceRange =
468         makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, m_texture.numLayers());
469     const VkImageMemoryBarrier barrierSetImageLayout =
470         makeImageMemoryBarrier(0u, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL,
471                                m_image->get(), subresourceRange);
472 
473     vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
474                           (VkDependencyFlags)0, 0, (const VkMemoryBarrier *)DE_NULL, 0,
475                           (const VkBufferMemoryBarrier *)DE_NULL, 1, &barrierSetImageLayout);
476 }
477 
478 class BufferSizeTestInstance : public SizeTestInstance
479 {
480 public:
481     BufferSizeTestInstance(Context &context, const Texture &texture, const VkFormat format);
482 
483 protected:
484     VkDescriptorSetLayout prepareDescriptors(void);
485 
commandBeforeCompute(const VkCommandBuffer)486     void commandBeforeCompute(const VkCommandBuffer)
487     {
488     }
getDescriptorSet(void) const489     VkDescriptorSet getDescriptorSet(void) const
490     {
491         return *m_descriptorSet;
492     }
493 
494     de::MovePtr<BufferWithMemory> m_imageBuffer;
495     Move<VkBufferView> m_bufferView;
496     Move<VkDescriptorSetLayout> m_descriptorSetLayout;
497     Move<VkDescriptorPool> m_descriptorPool;
498     Move<VkDescriptorSet> m_descriptorSet;
499 };
500 
BufferSizeTestInstance(Context & context,const Texture & texture,const VkFormat format)501 BufferSizeTestInstance::BufferSizeTestInstance(Context &context, const Texture &texture, const VkFormat format)
502     : SizeTestInstance(context, texture, format)
503 {
504     const DeviceInterface &vk = m_context.getDeviceInterface();
505     const VkDevice device     = m_context.getDevice();
506     Allocator &allocator      = m_context.getDefaultAllocator();
507 
508     // Create a texel storage buffer. Its data be uninitialized, as we're not reading from it.
509 
510     const VkDeviceSize imageSizeBytes = getImageSizeBytes(m_texture.size(), m_format);
511     m_imageBuffer                     = de::MovePtr<BufferWithMemory>(new BufferWithMemory(
512         vk, device, allocator, makeBufferCreateInfo(imageSizeBytes, VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT),
513         MemoryRequirement::Any));
514 
515     m_bufferView = makeBufferView(vk, device, m_imageBuffer->get(), m_format, 0ull, imageSizeBytes);
516 }
517 
prepareDescriptors(void)518 VkDescriptorSetLayout BufferSizeTestInstance::prepareDescriptors(void)
519 {
520     const DeviceInterface &vk = m_context.getDeviceInterface();
521     const VkDevice device     = m_context.getDevice();
522 
523     m_descriptorSetLayout = DescriptorSetLayoutBuilder()
524                                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
525                                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
526                                 .build(vk, device);
527 
528     m_descriptorPool = DescriptorPoolBuilder()
529                            .addType(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)
530                            .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
531                            .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
532 
533     m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
534 
535     const VkDescriptorBufferInfo descriptorBufferInfo =
536         makeDescriptorBufferInfo(m_resultBuffer->get(), 0ull, m_resultBufferSizeBytes);
537 
538     DescriptorSetUpdateBuilder()
539         .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
540                      VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, &m_bufferView.get())
541         .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u),
542                      VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorBufferInfo)
543         .update(vk, device);
544 
545     return *m_descriptorSetLayout;
546 }
547 
createInstance(Context & context) const548 TestInstance *SizeTest::createInstance(Context &context) const
549 {
550     if (m_texture.type() == IMAGE_TYPE_BUFFER)
551         return new BufferSizeTestInstance(context, m_texture, m_format);
552     else
553         return new ImageSizeTestInstance(context, m_texture, m_format, m_2DViewOf3D);
554 }
555 
556 } // namespace
557 
createImageSizeTests(tcu::TestContext & testCtx)558 tcu::TestCaseGroup *createImageSizeTests(tcu::TestContext &testCtx)
559 {
560     const ImageType s_imageTypes[] = {
561         IMAGE_TYPE_1D, IMAGE_TYPE_1D_ARRAY, IMAGE_TYPE_2D,         IMAGE_TYPE_2D_ARRAY,
562         IMAGE_TYPE_3D, IMAGE_TYPE_CUBE,     IMAGE_TYPE_CUBE_ARRAY, IMAGE_TYPE_BUFFER,
563     };
564 
565     //! Base sizes used to generate actual image/buffer sizes in the test.
566     const tcu::IVec3 s_baseImageSizes[] = {
567         tcu::IVec3(32, 32, 32),
568         tcu::IVec3(12, 34, 56),
569         tcu::IVec3(1, 1, 1),
570         tcu::IVec3(7, 1, 1),
571     };
572 
573     const uint32_t s_flags[] = {
574         SizeTest::FLAG_READONLY_IMAGE,
575         SizeTest::FLAG_WRITEONLY_IMAGE,
576         SizeTest::FLAG_READONLY_IMAGE | SizeTest::FLAG_WRITEONLY_IMAGE,
577     };
578 
579     de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "image_size"));
580 
581     const VkFormat format = VK_FORMAT_R32G32B32A32_SFLOAT;
582 
583     for (const auto &imageType : s_imageTypes)
584     {
585         de::MovePtr<tcu::TestCaseGroup> imageGroup(
586             new tcu::TestCaseGroup(testCtx, getImageTypeName(imageType).c_str()));
587 
588         for (const auto &flags : s_flags)
589             for (const auto &baseImageSize : s_baseImageSizes)
590                 for (int boolIdx = 0; boolIdx < 2; ++boolIdx)
591                 {
592                     const bool is2DViewOf3D = (boolIdx > 0);
593 
594 #ifdef CTS_USES_VULKANSC
595                     // VulkanSC doesn't have VK_EXT_image_2d_view_of_3d
596                     if (is2DViewOf3D)
597                         continue;
598 #endif // CTS_USES_VULKANSC
599 
600                     if (is2DViewOf3D && imageType != IMAGE_TYPE_3D)
601                         continue;
602 
603                     const Texture texture = getTexture(imageType, baseImageSize);
604                     const auto caseName   = getCaseName(texture, flags, is2DViewOf3D);
605 
606                     imageGroup->addChild(new SizeTest(testCtx, caseName, texture, format, flags, is2DViewOf3D));
607                 }
608 
609         testGroup->addChild(imageGroup.release());
610     }
611     return testGroup.release();
612 }
613 
614 } // namespace image
615 } // namespace vkt
616