1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2015 The Khronos Group Inc.
6 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
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 Vulkan Get Render Area Granularity Tests
23 *//*--------------------------------------------------------------------*/
24
25 #include "vktApiGranularityTests.hpp"
26
27 #include "deRandom.hpp"
28 #include "deSharedPtr.hpp"
29 #include "deStringUtil.hpp"
30 #include "deUniquePtr.hpp"
31
32 #include "vkImageUtil.hpp"
33 #include "vkMemUtil.hpp"
34 #include "vkQueryUtil.hpp"
35 #include "vkRefUtil.hpp"
36 #include "vkCmdUtil.hpp"
37 #include "vkTypeUtil.hpp"
38 #include "vktTestCase.hpp"
39
40 #include "tcuTestLog.hpp"
41 #include "tcuTextureUtil.hpp"
42
43 #include <string>
44
45 namespace vkt
46 {
47
48 namespace api
49 {
50
51 using namespace vk;
52
53 namespace
54 {
55
56 struct AttachmentInfo
57 {
AttachmentInfovkt::api::__anonfc51f3c80111::AttachmentInfo58 AttachmentInfo (const VkFormat vkFormat,
59 const deUint32 width,
60 const deUint32 height,
61 const deUint32 depth)
62 : format (vkFormat)
63 {
64 extent.width = width;
65 extent.height = height;
66 extent.depth = depth;
67 }
68
~AttachmentInfovkt::api::__anonfc51f3c80111::AttachmentInfo69 ~AttachmentInfo (void)
70 {}
71
72 VkFormat format;
73 VkExtent3D extent;
74 };
75
76 typedef de::SharedPtr<Allocation> AllocationSp;
77 typedef de::SharedPtr<Unique<VkImage> > VkImageSp;
78 typedef de::SharedPtr<Unique<VkImageView> > VkImageViewSp;
79
80 class GranularityInstance : public vkt::TestInstance
81 {
82 public:
83 GranularityInstance (Context& context,
84 const std::vector<AttachmentInfo>& attachments,
85 const bool useRenderPass);
86 virtual ~GranularityInstance (void);
87 void checkFormatSupport (const VkFormat format);
88 void initAttachmentDescriptions (void);
89 void initImages (void);
90 void initRenderPass (void);
91 void beginRenderPass (void);
92 void endRenderPass (void);
93 virtual tcu::TestStatus iterate (void);
94 private:
95 const std::vector<AttachmentInfo> m_attachments;
96 const bool m_useRenderPass;
97
98 Move<VkRenderPass> m_renderPass;
99 Move<VkFramebuffer> m_frameBuffer;
100 Move<VkCommandPool> m_cmdPool;
101 Move<VkCommandBuffer> m_cmdBuffer;
102 std::vector<VkAttachmentDescription> m_attachmentDescriptions;
103 std::vector<VkImageSp> m_images;
104 std::vector<AllocationSp> m_imageAllocs;
105 std::vector<VkImageViewSp> m_imageViews;
106 };
107
GranularityInstance(Context & context,const std::vector<AttachmentInfo> & attachments,const bool useRenderPass)108 GranularityInstance::GranularityInstance (Context& context,
109 const std::vector<AttachmentInfo>& attachments,
110 const bool useRenderPass)
111 : vkt::TestInstance (context)
112 , m_attachments (attachments)
113 , m_useRenderPass (useRenderPass)
114 {
115 initAttachmentDescriptions();
116 }
117
~GranularityInstance(void)118 GranularityInstance::~GranularityInstance (void)
119 {
120 }
121
checkFormatSupport(const VkFormat format)122 void GranularityInstance::checkFormatSupport (const VkFormat format)
123 {
124 VkImageFormatProperties properties;
125
126 VkResult result = m_context.getInstanceInterface().getPhysicalDeviceImageFormatProperties(m_context.getPhysicalDevice(),
127 format, VK_IMAGE_TYPE_2D,
128 VK_IMAGE_TILING_OPTIMAL,
129 VK_IMAGE_USAGE_SAMPLED_BIT,
130 0,
131 &properties);
132
133 if (result == VK_ERROR_FORMAT_NOT_SUPPORTED)
134 TCU_THROW(NotSupportedError, "Format not supported");
135 }
136
initAttachmentDescriptions(void)137 void GranularityInstance::initAttachmentDescriptions (void)
138 {
139 VkAttachmentDescription attachmentDescription =
140 {
141 0u, // VkAttachmentDescriptionFlags flags;
142 VK_FORMAT_UNDEFINED, // VkFormat format;
143 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
144 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp loadOp;
145 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp storeOp;
146 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
147 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
148 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
149 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout finalLayout;
150 };
151
152 for (std::vector<AttachmentInfo>::const_iterator it = m_attachments.begin(); it != m_attachments.end(); ++it)
153 {
154 checkFormatSupport(it->format);
155 attachmentDescription.format = it->format;
156 m_attachmentDescriptions.push_back(attachmentDescription);
157 }
158 }
159
initImages(void)160 void GranularityInstance::initImages (void)
161 {
162 const DeviceInterface& vk = m_context.getDeviceInterface();
163 const VkDevice device = m_context.getDevice();
164 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
165 SimpleAllocator memAlloc (vk, device, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
166
167 for (std::vector<AttachmentInfo>::const_iterator it = m_attachments.begin(); it != m_attachments.end(); ++it)
168 {
169 const VkImageCreateInfo imageInfo =
170 {
171 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
172 DE_NULL, // const void* pNext;
173 0u, // VkImageCreateFlags flags;
174 VK_IMAGE_TYPE_2D, // VkImageType imageType;
175 it->format, // VkFormat format;
176 it->extent, // VkExtent3D extent;
177 1u, // deUint32 mipLevels;
178 1u, // deUint32 arrayLayers;
179 VK_SAMPLE_COUNT_1_BIT, // deUint32 samples;
180 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
181 VK_IMAGE_USAGE_SAMPLED_BIT, // VkImageUsageFlags usage;
182 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
183 1u, // deUint32 queueFamilyCount;
184 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
185 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
186 };
187
188 // Create the image
189 Move<VkImage> image = createImage(vk, device, &imageInfo);
190 de::MovePtr<Allocation> imageAlloc = memAlloc.allocate(getImageMemoryRequirements(vk, device, *image), MemoryRequirement::Any);
191 VK_CHECK(vk.bindImageMemory(device, *image, imageAlloc->getMemory(), imageAlloc->getOffset()));
192
193 VkImageAspectFlags aspectFlags = 0;
194 const tcu::TextureFormat tcuFormat = mapVkFormat(it->format);
195
196 if (tcu::hasDepthComponent(tcuFormat.order))
197 aspectFlags |= VK_IMAGE_ASPECT_DEPTH_BIT;
198
199 if (tcu::hasStencilComponent(tcuFormat.order))
200 aspectFlags |= VK_IMAGE_ASPECT_STENCIL_BIT;
201
202 if (!aspectFlags)
203 aspectFlags = VK_IMAGE_ASPECT_COLOR_BIT;
204
205 VkFormatProperties formatProperties;
206 m_context.getInstanceInterface().getPhysicalDeviceFormatProperties(m_context.getPhysicalDevice(),
207 it->format, &formatProperties);
208
209 if ((formatProperties.optimalTilingFeatures & (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT |
210 VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) == 0)
211 throw tcu::NotSupportedError("Format not supported as attachment");
212
213 const VkImageViewCreateInfo createInfo =
214 {
215 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
216 DE_NULL, // const void* pNext;
217 0, // VkImageViewCreateFlags flags;
218 *image, // VkImage image;
219 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
220 it->format, // VkFormat format;
221 {
222 VK_COMPONENT_SWIZZLE_R,
223 VK_COMPONENT_SWIZZLE_G,
224 VK_COMPONENT_SWIZZLE_B,
225 VK_COMPONENT_SWIZZLE_A
226 }, // VkComponentMapping components;
227 { aspectFlags, 0u, 1u, 0u, 1u } // VkImageSubresourceRange subresourceRange;
228 };
229
230 // Create the Image View
231 Move<VkImageView> imageView = createImageView(vk, device, &createInfo);
232
233 // To prevent object free
234 m_images.push_back(VkImageSp(new Unique<VkImage>(image)));
235 m_imageAllocs.push_back(AllocationSp(imageAlloc.release()));
236 m_imageViews.push_back(VkImageViewSp(new Unique<VkImageView>(imageView)));
237 }
238 }
239
initRenderPass(void)240 void GranularityInstance::initRenderPass (void)
241 {
242 const DeviceInterface& vk = m_context.getDeviceInterface();
243 const VkDevice device = m_context.getDevice();
244 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
245
246 { // Create RenderPass
247 const VkSubpassDescription subpassDesc =
248 {
249 (VkSubpassDescriptionFlags)0u, // VkSubpassDescriptionFlags flags;
250 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
251 0u, // deUint32 inputCount;
252 DE_NULL, // const VkAttachmentReference* pInputAttachments;
253 0u, // deUint32 colorCount;
254 DE_NULL, // const VkAttachmentReference* pColorAttachments;
255 DE_NULL, // const VkAttachmentReference* pResolveAttachments;
256 DE_NULL, // VkAttachmentReference depthStencilAttachment;
257 0u, // deUint32 preserveCount;
258 DE_NULL // const VkAttachmentReference* pPreserveAttachments;
259 };
260
261 const VkRenderPassCreateInfo renderPassParams =
262 {
263 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
264 DE_NULL, // const void* pNext;
265 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags;
266 (deUint32)m_attachmentDescriptions.size(), // deUint32 attachmentCount;
267 &m_attachmentDescriptions[0], // const VkAttachmentDescription* pAttachments;
268 1u, // deUint32 subpassCount;
269 &subpassDesc, // const VkSubpassDescription* pSubpasses;
270 0u, // deUint32 dependencyCount;
271 DE_NULL // const VkSubpassDependency* pDependencies;
272 };
273
274 m_renderPass = createRenderPass(vk, device, &renderPassParams);
275 }
276
277 initImages();
278
279 { // Create Framebuffer
280 std::vector<VkImageView> imageViews;
281
282 for (std::vector<VkImageViewSp>::const_iterator it = m_imageViews.begin(); it != m_imageViews.end(); ++it)
283 imageViews.push_back(it->get()->get());
284
285 const VkFramebufferCreateInfo framebufferParams =
286 {
287 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
288 DE_NULL, // const void* pNext;
289 (VkFramebufferCreateFlags)0, // VkFramebufferCreateFlags flags;
290 *m_renderPass, // VkRenderPass renderPass;
291 (deUint32)imageViews.size(), // deUint32 attachmentCount;
292 &imageViews[0], // const VkImageView* pAttachments;
293 1, // deUint32 width;
294 1, // deUint32 height;
295 1 // deUint32 layers;
296 };
297
298 m_frameBuffer = createFramebuffer(vk, device, &framebufferParams);
299 }
300
301 m_cmdPool = createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
302
303 // Create CommandBuffer
304 m_cmdBuffer = allocateCommandBuffer(vk, device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
305
306 // Begin CommandBuffer
307 beginCommandBuffer(vk, *m_cmdBuffer, 0u);
308 }
309
beginRenderPass(void)310 void GranularityInstance::beginRenderPass (void)
311 {
312 const DeviceInterface& vk = m_context.getDeviceInterface();
313
314 const VkRect2D renderArea = makeRect2D(1u, 1u);
315
316 vk::beginRenderPass(vk, *m_cmdBuffer, *m_renderPass, *m_frameBuffer, renderArea);
317 }
318
endRenderPass(void)319 void GranularityInstance::endRenderPass (void)
320 {
321 const DeviceInterface& vk = m_context.getDeviceInterface();
322
323 vk::endRenderPass(vk, *m_cmdBuffer);
324 endCommandBuffer(vk, *m_cmdBuffer);
325 }
326
iterate(void)327 tcu::TestStatus GranularityInstance::iterate (void)
328 {
329 const DeviceInterface& vk = m_context.getDeviceInterface();
330 const VkDevice device = m_context.getDevice();
331 tcu::TestLog& log = m_context.getTestContext().getLog();
332
333 initRenderPass();
334
335 VkExtent2D prePassGranularity = { ~0u, ~0u };
336 vk.getRenderAreaGranularity(device, *m_renderPass, &prePassGranularity);
337
338 if(m_useRenderPass)
339 beginRenderPass();
340
341 VkExtent2D granularity = { 0u, 0u };
342 vk.getRenderAreaGranularity(device, *m_renderPass, &granularity);
343 TCU_CHECK(granularity.width >= 1 && granularity.height >= 1);
344 TCU_CHECK(prePassGranularity.width == granularity.width && prePassGranularity.height == granularity.height);
345 TCU_CHECK(granularity.width <= m_context.getDeviceProperties().limits.maxFramebufferWidth && granularity.height <= m_context.getDeviceProperties().limits.maxFramebufferHeight);
346
347 if(m_useRenderPass)
348 endRenderPass();
349
350 log << tcu::TestLog::Message << "Horizontal granularity: " << granularity.width << " Vertical granularity: " << granularity.height << tcu::TestLog::EndMessage;
351 return tcu::TestStatus::pass("Granularity test");
352 }
353
354 class GranularityCase : public vkt::TestCase
355 {
356 public:
357 GranularityCase (tcu::TestContext& testCtx,
358 const std::string& name,
359 const std::string& description,
360 const std::vector<AttachmentInfo>& attachments,
361 const bool useRenderPass);
362 virtual ~GranularityCase (void);
363
364 virtual TestInstance* createInstance (Context& context) const;
365 private:
366 const std::vector<AttachmentInfo> m_attachments;
367 const bool m_useRenderPass;
368 };
369
GranularityCase(tcu::TestContext & testCtx,const std::string & name,const std::string & description,const std::vector<AttachmentInfo> & attachments,const bool useRenderPass=false)370 GranularityCase::GranularityCase (tcu::TestContext& testCtx,
371 const std::string& name,
372 const std::string& description,
373 const std::vector<AttachmentInfo>& attachments,
374 const bool useRenderPass = false)
375 : vkt::TestCase (testCtx, name, description)
376 , m_attachments (attachments)
377 , m_useRenderPass (useRenderPass)
378 {
379 }
380
~GranularityCase(void)381 GranularityCase::~GranularityCase (void)
382 {
383 }
384
createInstance(Context & context) const385 TestInstance* GranularityCase::createInstance (Context& context) const
386 {
387 return new GranularityInstance(context, m_attachments, m_useRenderPass);
388 }
389
390 } // anonymous
391
createGranularityQueryTests(tcu::TestContext & testCtx)392 tcu::TestCaseGroup* createGranularityQueryTests (tcu::TestContext& testCtx)
393 {
394 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "granularity", "Granularity query tests"));
395 // Subgroups
396 de::MovePtr<tcu::TestCaseGroup> single (new tcu::TestCaseGroup(testCtx, "single", "Single texture granularity tests."));
397 de::MovePtr<tcu::TestCaseGroup> multi (new tcu::TestCaseGroup(testCtx, "multi", "Multiple textures with same format granularity tests."));
398 de::MovePtr<tcu::TestCaseGroup> random (new tcu::TestCaseGroup(testCtx, "random", "Multiple textures with a guaranteed format occurence."));
399 de::MovePtr<tcu::TestCaseGroup> inRenderPass (new tcu::TestCaseGroup(testCtx, "in_render_pass", "Single texture granularity tests, inside render pass"));
400
401 de::Random rnd(215);
402 const char* description = "Granularity case.";
403
404 const VkFormat mandatoryFormats[] =
405 {
406 VK_FORMAT_B4G4R4A4_UNORM_PACK16,
407 VK_FORMAT_R5G6B5_UNORM_PACK16,
408 VK_FORMAT_A1R5G5B5_UNORM_PACK16,
409 VK_FORMAT_R8_UNORM,
410 VK_FORMAT_R8_SNORM,
411 VK_FORMAT_R8_UINT,
412 VK_FORMAT_R8_SINT,
413 VK_FORMAT_R8G8_UNORM,
414 VK_FORMAT_R8G8_SNORM,
415 VK_FORMAT_R8G8_UINT,
416 VK_FORMAT_R8G8_SINT,
417 VK_FORMAT_R8G8B8A8_UNORM,
418 VK_FORMAT_R8G8B8A8_SNORM,
419 VK_FORMAT_R8G8B8A8_UINT,
420 VK_FORMAT_R8G8B8A8_SINT,
421 VK_FORMAT_R8G8B8A8_SRGB,
422 VK_FORMAT_B8G8R8A8_UNORM,
423 VK_FORMAT_B8G8R8A8_SRGB,
424 VK_FORMAT_A8B8G8R8_UNORM_PACK32,
425 VK_FORMAT_A8B8G8R8_SNORM_PACK32,
426 VK_FORMAT_A8B8G8R8_UINT_PACK32,
427 VK_FORMAT_A8B8G8R8_SINT_PACK32,
428 VK_FORMAT_A8B8G8R8_SRGB_PACK32,
429 VK_FORMAT_A2B10G10R10_UNORM_PACK32,
430 VK_FORMAT_A2B10G10R10_UINT_PACK32,
431 VK_FORMAT_R16_UINT,
432 VK_FORMAT_R16_SINT,
433 VK_FORMAT_R16_SFLOAT,
434 VK_FORMAT_R16G16_UINT,
435 VK_FORMAT_R16G16_SINT,
436 VK_FORMAT_R16G16_SFLOAT,
437 VK_FORMAT_R16G16B16A16_UINT,
438 VK_FORMAT_R16G16B16A16_SINT,
439 VK_FORMAT_R16G16B16A16_SFLOAT,
440 VK_FORMAT_R32_UINT,
441 VK_FORMAT_R32_SINT,
442 VK_FORMAT_R32_SFLOAT,
443 VK_FORMAT_R32G32_UINT,
444 VK_FORMAT_R32G32_SINT,
445 VK_FORMAT_R32G32_SFLOAT,
446 VK_FORMAT_R32G32B32A32_UINT,
447 VK_FORMAT_R32G32B32A32_SINT,
448 VK_FORMAT_R32G32B32A32_SFLOAT,
449 VK_FORMAT_B10G11R11_UFLOAT_PACK32,
450 VK_FORMAT_E5B9G9R9_UFLOAT_PACK32,
451 VK_FORMAT_D16_UNORM,
452 VK_FORMAT_D32_SFLOAT,
453 };
454
455 const deUint32 maxDimension = 500;
456 const deUint32 minIteration = 2;
457 const deUint32 maxIteration = 10;
458
459 for (deUint32 formatIdx = 1; formatIdx <= VK_FORMAT_D32_SFLOAT_S8_UINT; ++formatIdx)
460 {
461 VkFormat format = VkFormat(formatIdx);
462 std::string name = de::toLower(getFormatName(format)).substr(10);
463
464 {
465 std::vector<AttachmentInfo> attachments;
466 const int i0 = rnd.getInt(1, maxDimension);
467 const int i1 = rnd.getInt(1, maxDimension);
468 attachments.push_back(AttachmentInfo(format, i0, i1, 1));
469 single->addChild(new GranularityCase(testCtx, name.c_str(), description, attachments));
470 }
471
472 {
473 std::vector<AttachmentInfo> attachments;
474 const deUint32 iterations = rnd.getInt(minIteration, maxIteration);
475 const int i0 = rnd.getInt(1, maxDimension);
476 const int i1 = rnd.getInt(1, maxDimension);
477 for (deUint32 idx = 0; idx < iterations; ++idx)
478 attachments.push_back(AttachmentInfo(VkFormat(formatIdx), i0, i1, 1));
479 multi->addChild(new GranularityCase(testCtx, name.c_str(), description, attachments));
480 }
481
482 {
483 std::vector<AttachmentInfo> attachments;
484 const deUint32 iterations = rnd.getInt(minIteration, maxIteration);
485 const int i0 = rnd.getInt(1, maxDimension);
486 const int i1 = rnd.getInt(1, maxDimension);
487 attachments.push_back(AttachmentInfo(VkFormat(formatIdx), i0, i1, 1));
488 for (deUint32 idx = 0; idx < iterations; ++idx)
489 {
490 const int i2 = rnd.getInt(0, DE_LENGTH_OF_ARRAY(mandatoryFormats) - 1);
491 const int i3 = rnd.getInt(1, maxDimension);
492 const int i4 = rnd.getInt(1, maxDimension);
493 attachments.push_back(AttachmentInfo(mandatoryFormats[i2], i3, i4, 1));
494 }
495 random->addChild(new GranularityCase(testCtx, name.c_str(), description, attachments));
496 }
497
498 {
499 std::vector<AttachmentInfo> attachments;
500 const int i0 = rnd.getInt(1, maxDimension);
501 const int i1 = rnd.getInt(1, maxDimension);
502 attachments.push_back(AttachmentInfo(format, i0, i1, 1));
503 inRenderPass->addChild(new GranularityCase(testCtx, name.c_str(), description, attachments, true));
504 }
505 }
506
507 group->addChild(single.release());
508 group->addChild(multi.release());
509 group->addChild(random.release());
510 group->addChild(inRenderPass.release());
511
512 return group.release();
513 }
514
515 } // api
516 } // vkt
517