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 {
105 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
106 DE_NULL, // const void* pNext;
107 createFlags, // VkImageCreateFlags flags;
108 mapImageType(texture.type()), // VkImageType imageType;
109 format, // VkFormat format;
110 makeExtent3D(texture.layerSize()), // VkExtent3D extent;
111 1u, // deUint32 mipLevels;
112 (deUint32)texture.numLayers(), // deUint32 arrayLayers;
113 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
114 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
115 VK_IMAGE_USAGE_STORAGE_BIT, // VkImageUsageFlags usage;
116 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
117 0u, // deUint32 queueFamilyIndexCount;
118 DE_NULL, // const deUint32* pQueueFamilyIndices;
119 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
120 };
121 return imageParams;
122 }
123
124 //! Interpret the memory as IVec3
readIVec3(const void * const data)125 inline tcu::IVec3 readIVec3 (const void* const data)
126 {
127 const int* const p = reinterpret_cast<const int*>(data);
128 return tcu::IVec3(p[0], p[1], p[2]);
129 }
130
getExpectedImageSizeResult(const Texture & texture,const bool is2DViewOf3D)131 tcu::IVec3 getExpectedImageSizeResult (const Texture& texture, const bool is2DViewOf3D)
132 {
133 // GLSL imageSize() function returns:
134 // z = 0 for cubes
135 // z = N for cube arrays, where N is the number of cubes
136 // y or z = L where L is the number of layers for other array types (e.g. 1D array, 2D array)
137 // z = D where D is the depth of 3d image
138
139 const tcu::IVec3 size = texture.size();
140 const int numCubeFaces = 6;
141
142 switch (texture.type())
143 {
144 case IMAGE_TYPE_1D:
145 case IMAGE_TYPE_BUFFER:
146 return tcu::IVec3(size.x(), 0, 0);
147
148 case IMAGE_TYPE_1D_ARRAY:
149 case IMAGE_TYPE_2D:
150 case IMAGE_TYPE_CUBE:
151 return tcu::IVec3(size.x(), size.y(), 0);
152
153 case IMAGE_TYPE_2D_ARRAY:
154 case IMAGE_TYPE_3D:
155 {
156 if (is2DViewOf3D)
157 return tcu::IVec3(size.x(), size.y(), 0);
158 return size;
159 }
160
161 case IMAGE_TYPE_CUBE_ARRAY:
162 return tcu::IVec3(size.x(), size.y(), size.z() / numCubeFaces);
163
164 default:
165 DE_FATAL("Internal error");
166 return tcu::IVec3();
167 }
168 }
169
170 class SizeTest : public TestCase
171 {
172 public:
173 enum TestFlags
174 {
175 FLAG_READONLY_IMAGE = 1u << 0,
176 FLAG_WRITEONLY_IMAGE = 1u << 1,
177 };
178
179 SizeTest (tcu::TestContext& testCtx,
180 const std::string& name,
181 const std::string& description,
182 const Texture& texture,
183 const VkFormat format,
184 const deUint32 flags,
185 const bool is2DViewOf3D);
186
187 void initPrograms (SourceCollections& programCollection) const;
188 TestInstance* createInstance (Context& context) const;
189 virtual void checkSupport (Context& context) const;
190
191 private:
192 const Texture m_texture;
193 const VkFormat m_format;
194 const bool m_useReadonly;
195 const bool m_useWriteonly;
196 const bool m_2DViewOf3D;
197 };
198
SizeTest(tcu::TestContext & testCtx,const std::string & name,const std::string & description,const Texture & texture,const VkFormat format,const deUint32 flags,const bool is2DViewOf3D)199 SizeTest::SizeTest (tcu::TestContext& testCtx,
200 const std::string& name,
201 const std::string& description,
202 const Texture& texture,
203 const VkFormat format,
204 const deUint32 flags,
205 const bool is2DViewOf3D)
206 : TestCase (testCtx, name, description)
207 , m_texture (texture)
208 , m_format (format)
209 , m_useReadonly ((flags & FLAG_READONLY_IMAGE) != 0)
210 , m_useWriteonly ((flags & FLAG_WRITEONLY_IMAGE) != 0)
211 , m_2DViewOf3D (is2DViewOf3D)
212 {
213 // We expect at least one flag to be set.
214 DE_ASSERT(m_useReadonly || m_useWriteonly);
215
216 // For 2D views of 3D we need 3D images.
217 DE_ASSERT(!m_2DViewOf3D || m_texture.type() == IMAGE_TYPE_3D);
218 }
219
checkSupport(Context & context) const220 void SizeTest::checkSupport (Context& context) const
221 {
222 const auto imgType = m_texture.type();
223
224 if (imgType == IMAGE_TYPE_CUBE_ARRAY)
225 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_IMAGE_CUBE_ARRAY);
226
227 if (imgType != IMAGE_TYPE_BUFFER)
228 {
229 const auto& vki = context.getInstanceInterface();
230 const auto physicalDevice = context.getPhysicalDevice();
231 const auto createInfo = makeImageCreateInfo(m_texture, m_format, m_2DViewOf3D);
232 VkImageFormatProperties formatProperties;
233
234 const auto result = vki.getPhysicalDeviceImageFormatProperties(physicalDevice, createInfo.format, createInfo.imageType, createInfo.tiling, createInfo.usage, createInfo.flags, &formatProperties);
235
236 if (result == VK_ERROR_FORMAT_NOT_SUPPORTED)
237 TCU_THROW(NotSupportedError, "Format not supported for the specified usage");
238 }
239
240 if (m_2DViewOf3D)
241 context.requireDeviceFunctionality("VK_EXT_image_2d_view_of_3d");
242 }
243
initPrograms(SourceCollections & programCollection) const244 void SizeTest::initPrograms (SourceCollections& programCollection) const
245 {
246 const std::string formatQualifierStr = getShaderImageFormatQualifier(mapVkFormat(m_format));
247 const std::string imageTypeStr = getShaderImageType(mapVkFormat(m_format), (m_2DViewOf3D ? IMAGE_TYPE_2D : m_texture.type()));
248 const int dimension = m_texture.dimension();
249
250 std::ostringstream accessQualifier;
251 if (m_useReadonly)
252 accessQualifier << " readonly";
253 if (m_useWriteonly)
254 accessQualifier << " writeonly";
255
256 std::ostringstream src;
257 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
258 << "\n"
259 << "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
260 << "layout (binding = 0, " << formatQualifierStr << ")" << accessQualifier.str() << " uniform highp " << imageTypeStr << " u_image;\n"
261 << "layout (binding = 1) writeonly buffer Output {\n"
262 << " ivec3 size;\n"
263 << "} sb_out;\n"
264 << "\n"
265 << "void main (void)\n"
266 << "{\n"
267 << (dimension == 1 ?
268 " sb_out.size = ivec3(imageSize(u_image), 0, 0);\n"
269 : dimension == 2 || m_2DViewOf3D || m_texture.type() == IMAGE_TYPE_CUBE ? // cubes return ivec2
270 " sb_out.size = ivec3(imageSize(u_image), 0);\n"
271 : dimension == 3 ? // cube arrays return ivec3
272 " sb_out.size = imageSize(u_image);\n"
273 : "")
274 << "}\n";
275
276 programCollection.glslSources.add("comp") << glu::ComputeSource(src.str());
277 }
278
279 //! Build a case name, e.g. "readonly_writeonly_32x32"
getCaseName(const Texture & texture,const deUint32 flags,const bool is2DViewOf3D)280 std::string getCaseName (const Texture& texture, const deUint32 flags, const bool is2DViewOf3D)
281 {
282 std::ostringstream str;
283 str << ((flags & SizeTest::FLAG_READONLY_IMAGE) != 0 ? "readonly_" : "")
284 << ((flags & SizeTest::FLAG_WRITEONLY_IMAGE) != 0 ? "writeonly_" : "");
285
286 if (is2DViewOf3D)
287 str << "2d_view_";
288
289 const int numComponents = texture.dimension();
290 for (int i = 0; i < numComponents; ++i)
291 str << (i == 0 ? "" : "x") << texture.size()[i];
292
293 return str.str();
294 }
295
296 //! Base test instance for image and buffer tests
297 class SizeTestInstance : public TestInstance
298 {
299 public:
300 SizeTestInstance (Context& context,
301 const Texture& texture,
302 const VkFormat format,
303 const bool is2DViewOf3D = false);
304
305 tcu::TestStatus iterate (void);
~SizeTestInstance(void)306 virtual ~SizeTestInstance (void) {}
307
308 protected:
309 virtual VkDescriptorSetLayout prepareDescriptors (void) = 0;
310 virtual VkDescriptorSet getDescriptorSet (void) const = 0;
311 virtual void commandBeforeCompute (const VkCommandBuffer cmdBuffer) = 0;
312
313 const Texture m_texture;
314 const VkFormat m_format;
315 const VkDeviceSize m_resultBufferSizeBytes;
316 const bool m_2DViewOf3D;
317 de::MovePtr<BufferWithMemory> m_resultBuffer; //!< Shader writes the output here.
318 };
319
SizeTestInstance(Context & context,const Texture & texture,const VkFormat format,const bool is2DViewOf3D)320 SizeTestInstance::SizeTestInstance (Context& context, const Texture& texture, const VkFormat format, const bool is2DViewOf3D)
321 : TestInstance (context)
322 , m_texture (texture)
323 , m_format (format)
324 , m_resultBufferSizeBytes (3 * sizeof(deUint32)) // ivec3 in shader
325 , m_2DViewOf3D (is2DViewOf3D)
326 {
327 const DeviceInterface& vk = m_context.getDeviceInterface();
328 const VkDevice device = m_context.getDevice();
329 Allocator& allocator = m_context.getDefaultAllocator();
330
331 // Create an SSBO for shader output.
332
333 m_resultBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(
334 vk, device, allocator,
335 makeBufferCreateInfo(m_resultBufferSizeBytes, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT),
336 MemoryRequirement::HostVisible));
337 }
338
iterate(void)339 tcu::TestStatus SizeTestInstance::iterate (void)
340 {
341 const DeviceInterface& vk = m_context.getDeviceInterface();
342 const VkDevice device = m_context.getDevice();
343 const VkQueue queue = m_context.getUniversalQueue();
344 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
345
346 // Create memory barriers.
347
348 const VkBufferMemoryBarrier shaderWriteBarrier = makeBufferMemoryBarrier(
349 VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT,
350 m_resultBuffer->get(), 0ull, m_resultBufferSizeBytes);
351
352 // Create the pipeline.
353
354 const Unique<VkShaderModule> shaderModule(createShaderModule(vk, device, m_context.getBinaryCollection().get("comp"), 0));
355
356 const VkDescriptorSetLayout descriptorSetLayout = prepareDescriptors();
357 const VkDescriptorSet descriptorSet = getDescriptorSet();
358
359 const Unique<VkPipelineLayout> pipelineLayout(makePipelineLayout(vk, device, descriptorSetLayout));
360 const Unique<VkPipeline> pipeline(makeComputePipeline(vk, device, *pipelineLayout, *shaderModule));
361
362 const Unique<VkCommandPool> cmdPool(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
363 const Unique<VkCommandBuffer> cmdBuffer(allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
364
365 beginCommandBuffer(vk, *cmdBuffer);
366
367 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
368 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &descriptorSet, 0u, DE_NULL);
369
370 commandBeforeCompute(*cmdBuffer);
371 vk.cmdDispatch(*cmdBuffer, 1, 1, 1);
372 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &shaderWriteBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL);
373
374 endCommandBuffer(vk, *cmdBuffer);
375
376 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
377
378 // Compare the result.
379
380 const Allocation& bufferAlloc = m_resultBuffer->getAllocation();
381 invalidateAlloc(vk, device, bufferAlloc);
382
383 const tcu::IVec3 resultSize = readIVec3(bufferAlloc.getHostPtr());
384 const tcu::IVec3 expectedSize = getExpectedImageSizeResult(m_texture, m_2DViewOf3D);
385
386 if (resultSize != expectedSize)
387 return tcu::TestStatus::fail("Incorrect imageSize(): expected " + de::toString(expectedSize) + " but got " + de::toString(resultSize));
388 else
389 return tcu::TestStatus::pass("Passed");
390 }
391
392 class ImageSizeTestInstance : public SizeTestInstance
393 {
394 public:
395 ImageSizeTestInstance (Context& context,
396 const Texture& texture,
397 const VkFormat format,
398 const bool is2DViewOf3D);
399
400 protected:
401 VkDescriptorSetLayout prepareDescriptors (void);
402 void commandBeforeCompute (const VkCommandBuffer cmdBuffer);
403
getDescriptorSet(void) const404 VkDescriptorSet getDescriptorSet (void) const { return *m_descriptorSet; }
405
406 de::MovePtr<Image> m_image;
407 Move<VkImageView> m_imageView;
408 Move<VkDescriptorSetLayout> m_descriptorSetLayout;
409 Move<VkDescriptorPool> m_descriptorPool;
410 Move<VkDescriptorSet> m_descriptorSet;
411 };
412
ImageSizeTestInstance(Context & context,const Texture & texture,const VkFormat format,const bool is2DViewOf3D)413 ImageSizeTestInstance::ImageSizeTestInstance (Context& context, const Texture& texture, const VkFormat format, const bool is2DViewOf3D)
414 : SizeTestInstance (context, texture, format, is2DViewOf3D)
415 {
416 const DeviceInterface& vk = m_context.getDeviceInterface();
417 const VkDevice device = m_context.getDevice();
418 Allocator& allocator = m_context.getDefaultAllocator();
419
420 // Create an image. Its data will be uninitialized, as we're not reading from it.
421
422 m_image = de::MovePtr<Image>(new Image(vk, device, allocator, makeImageCreateInfo(m_texture, m_format, m_2DViewOf3D), MemoryRequirement::Any));
423
424 const auto baseLayer = (m_2DViewOf3D ? static_cast<uint32_t>(m_texture.size().z() / 2) : 0u);
425 const auto viewType = (m_2DViewOf3D ? VK_IMAGE_VIEW_TYPE_2D : mapImageViewType(m_texture.type()));
426 const auto subresourceRange = 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 = makeDescriptorImageInfo(DE_NULL, *m_imageView, VK_IMAGE_LAYOUT_GENERAL);
449 const VkDescriptorBufferInfo descriptorBufferInfo = makeDescriptorBufferInfo(m_resultBuffer->get(), 0ull, m_resultBufferSizeBytes);
450
451 DescriptorSetUpdateBuilder()
452 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
453 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorBufferInfo)
454 .update(vk, device);
455
456 return *m_descriptorSetLayout;
457 }
458
commandBeforeCompute(const VkCommandBuffer cmdBuffer)459 void ImageSizeTestInstance::commandBeforeCompute (const VkCommandBuffer cmdBuffer)
460 {
461 const DeviceInterface& vk = m_context.getDeviceInterface();
462
463 const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, m_texture.numLayers());
464 const VkImageMemoryBarrier barrierSetImageLayout = makeImageMemoryBarrier(
465 0u, VK_ACCESS_SHADER_READ_BIT,
466 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL,
467 m_image->get(), subresourceRange);
468
469 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &barrierSetImageLayout);
470 }
471
472 class BufferSizeTestInstance : public SizeTestInstance
473 {
474 public:
475 BufferSizeTestInstance (Context& context,
476 const Texture& texture,
477 const VkFormat format);
478
479 protected:
480 VkDescriptorSetLayout prepareDescriptors (void);
481
commandBeforeCompute(const VkCommandBuffer)482 void commandBeforeCompute (const VkCommandBuffer) {}
getDescriptorSet(void) const483 VkDescriptorSet getDescriptorSet (void) const { return *m_descriptorSet; }
484
485 de::MovePtr<BufferWithMemory> m_imageBuffer;
486 Move<VkBufferView> m_bufferView;
487 Move<VkDescriptorSetLayout> m_descriptorSetLayout;
488 Move<VkDescriptorPool> m_descriptorPool;
489 Move<VkDescriptorSet> m_descriptorSet;
490 };
491
BufferSizeTestInstance(Context & context,const Texture & texture,const VkFormat format)492 BufferSizeTestInstance::BufferSizeTestInstance (Context& context, const Texture& texture, const VkFormat format)
493 : SizeTestInstance (context, texture, format)
494 {
495 const DeviceInterface& vk = m_context.getDeviceInterface();
496 const VkDevice device = m_context.getDevice();
497 Allocator& allocator = m_context.getDefaultAllocator();
498
499 // Create a texel storage buffer. Its data be uninitialized, as we're not reading from it.
500
501 const VkDeviceSize imageSizeBytes = getImageSizeBytes(m_texture.size(), m_format);
502 m_imageBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(vk, device, allocator,
503 makeBufferCreateInfo(imageSizeBytes, VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT), MemoryRequirement::Any));
504
505 m_bufferView = makeBufferView(vk, device, m_imageBuffer->get(), m_format, 0ull, imageSizeBytes);
506 }
507
prepareDescriptors(void)508 VkDescriptorSetLayout BufferSizeTestInstance::prepareDescriptors (void)
509 {
510 const DeviceInterface& vk = m_context.getDeviceInterface();
511 const VkDevice device = m_context.getDevice();
512
513 m_descriptorSetLayout = DescriptorSetLayoutBuilder()
514 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
515 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
516 .build(vk, device);
517
518 m_descriptorPool = DescriptorPoolBuilder()
519 .addType(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)
520 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
521 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
522
523 m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
524
525 const VkDescriptorBufferInfo descriptorBufferInfo = makeDescriptorBufferInfo(m_resultBuffer->get(), 0ull, m_resultBufferSizeBytes);
526
527 DescriptorSetUpdateBuilder()
528 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, &m_bufferView.get())
529 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorBufferInfo)
530 .update(vk, device);
531
532 return *m_descriptorSetLayout;
533 }
534
createInstance(Context & context) const535 TestInstance* SizeTest::createInstance (Context& context) const
536 {
537 if (m_texture.type() == IMAGE_TYPE_BUFFER)
538 return new BufferSizeTestInstance(context, m_texture, m_format);
539 else
540 return new ImageSizeTestInstance(context, m_texture, m_format, m_2DViewOf3D);
541 }
542
543 } // anonymous ns
544
createImageSizeTests(tcu::TestContext & testCtx)545 tcu::TestCaseGroup* createImageSizeTests (tcu::TestContext& testCtx)
546 {
547 const ImageType s_imageTypes[] =
548 {
549 IMAGE_TYPE_1D,
550 IMAGE_TYPE_1D_ARRAY,
551 IMAGE_TYPE_2D,
552 IMAGE_TYPE_2D_ARRAY,
553 IMAGE_TYPE_3D,
554 IMAGE_TYPE_CUBE,
555 IMAGE_TYPE_CUBE_ARRAY,
556 IMAGE_TYPE_BUFFER,
557 };
558
559 //! Base sizes used to generate actual image/buffer sizes in the test.
560 const tcu::IVec3 s_baseImageSizes[] =
561 {
562 tcu::IVec3(32, 32, 32),
563 tcu::IVec3(12, 34, 56),
564 tcu::IVec3(1, 1, 1),
565 tcu::IVec3(7, 1, 1),
566 };
567
568 const deUint32 s_flags[] =
569 {
570 SizeTest::FLAG_READONLY_IMAGE,
571 SizeTest::FLAG_WRITEONLY_IMAGE,
572 SizeTest::FLAG_READONLY_IMAGE | SizeTest::FLAG_WRITEONLY_IMAGE,
573 };
574
575 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "image_size", "imageSize() cases"));
576
577 const VkFormat format = VK_FORMAT_R32G32B32A32_SFLOAT;
578
579 for (const auto& imageType : s_imageTypes)
580 {
581 de::MovePtr<tcu::TestCaseGroup> imageGroup(new tcu::TestCaseGroup(testCtx, getImageTypeName(imageType).c_str(), ""));
582
583 for (const auto& flags : s_flags)
584 for (const auto& baseImageSize : s_baseImageSizes)
585 for (int boolIdx = 0; boolIdx < 2; ++boolIdx)
586 {
587 const bool is2DViewOf3D = (boolIdx > 0);
588
589 #ifdef CTS_USES_VULKANSC
590 // VulkanSC doesn't have VK_EXT_image_2d_view_of_3d
591 if (is2DViewOf3D)
592 continue;
593 #endif // CTS_USES_VULKANSC
594
595 if (is2DViewOf3D && imageType != IMAGE_TYPE_3D)
596 continue;
597
598 const Texture texture = getTexture(imageType, baseImageSize);
599 const auto caseName = getCaseName(texture, flags, is2DViewOf3D);
600
601 imageGroup->addChild(new SizeTest(testCtx, caseName, "", texture, format, flags, is2DViewOf3D));
602 }
603
604 testGroup->addChild(imageGroup.release());
605 }
606 return testGroup.release();
607 }
608
609 } // image
610 } // vkt
611