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