1 /*-------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2017 Google Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Tests for render pass multisample resolve
22 *//*--------------------------------------------------------------------*/
23
24 #include "vktRenderPassMultisampleResolveTests.hpp"
25 #include "vktRenderPassTestsUtil.hpp"
26
27 #include "vktTestCaseUtil.hpp"
28 #include "vktTestGroupUtil.hpp"
29
30 #include "vkDefs.hpp"
31 #include "vkDeviceUtil.hpp"
32 #include "vkImageUtil.hpp"
33 #include "vkMemUtil.hpp"
34 #include "vkPlatform.hpp"
35 #include "vkPrograms.hpp"
36 #include "vkQueryUtil.hpp"
37 #include "vkRef.hpp"
38 #include "vkRefUtil.hpp"
39 #include "vkTypeUtil.hpp"
40 #include "vkCmdUtil.hpp"
41 #include "vkObjUtil.hpp"
42
43 #include "tcuFloat.hpp"
44 #include "tcuImageCompare.hpp"
45 #include "tcuFormatUtil.hpp"
46 #include "tcuMaybe.hpp"
47 #include "tcuResultCollector.hpp"
48 #include "tcuTestLog.hpp"
49 #include "tcuTextureUtil.hpp"
50 #include "tcuVectorUtil.hpp"
51 #include "tcuStringTemplate.hpp"
52
53 #include "deUniquePtr.hpp"
54 #include "deSharedPtr.hpp"
55
56 using namespace vk;
57
58 using tcu::BVec4;
59 using tcu::IVec2;
60 using tcu::IVec4;
61 using tcu::UVec2;
62 using tcu::UVec4;
63 using tcu::Vec2;
64 using tcu::Vec3;
65 using tcu::Vec4;
66
67 using tcu::ConstPixelBufferAccess;
68 using tcu::PixelBufferAccess;
69 using tcu::TestLog;
70
71 using std::vector;
72
73 typedef de::SharedPtr<Allocation> AllocationSp;
74 typedef de::SharedPtr<vk::Unique<VkImage> > VkImageSp;
75 typedef de::SharedPtr<vk::Unique<VkImageView> > VkImageViewSp;
76 typedef de::SharedPtr<vk::Unique<VkBuffer> > VkBufferSp;
77 typedef de::SharedPtr<vk::Unique<VkSampler> > VkSamplerSp;
78 typedef de::SharedPtr<vk::Unique<VkPipeline> > VkPipelineSp;
79 typedef de::SharedPtr<vk::Unique<VkDescriptorSetLayout> > VkDescriptorSetLayoutSp;
80 typedef de::SharedPtr<vk::Unique<VkDescriptorPool> > VkDescriptorPoolSp;
81 typedef de::SharedPtr<vk::Unique<VkDescriptorSet> > VkDescriptorSetSp;
82
83 namespace vkt
84 {
85 namespace
86 {
87
88 using namespace renderpass;
89
90 template<typename T>
safeSharedPtr(T* ptr)91 de::SharedPtr<T> safeSharedPtr (T* ptr)
92 {
93 try
94 {
95 return de::SharedPtr<T>(ptr);
96 }
97 catch (...)
98 {
99 delete ptr;
100 throw;
101 }
102 }
103
104 enum TestType
105 {
106 RESOLVE = 0,
107 MAX_ATTACHMENTS,
108 COMPATIBILITY
109 };
110
111 struct TestConfig
112 {
113 TestType testType;
114 VkFormat format;
115 deUint32 sampleCount;
116 deUint32 layerCount;
117 deUint32 attachmentCount;
118 deUint32 width;
119 deUint32 height;
120 const SharedGroupParams groupParams;
121 };
122
123 struct TestConfig2 : TestConfig
124 {
TestConfig2vkt::__anon29771::TestConfig2125 TestConfig2(const TestConfig& src, deUint32 level)
126 : TestConfig (src)
127 , resolveLevel (level)
128 {
129 }
130 deUint32 resolveLevel;
131 };
132
133 // Render pass traits that groups render pass related types together and by that help
134 // to reduce number of template parrameters passed to number of functions in those tests
135 struct RenderPass1Trait
136 {
137 typedef AttachmentDescription1 AttDesc;
138 typedef AttachmentReference1 AttRef;
139 typedef SubpassDescription1 SubpassDesc;
140 typedef SubpassDependency1 SubpassDep;
141 typedef RenderPassCreateInfo1 RenderPassCreateInfo;
142 };
143 struct RenderPass2Trait
144 {
145 typedef AttachmentDescription2 AttDesc;
146 typedef AttachmentReference2 AttRef;
147 typedef SubpassDescription2 SubpassDesc;
148 typedef SubpassDependency2 SubpassDep;
149 typedef RenderPassCreateInfo2 RenderPassCreateInfo;
150 };
151
152 class MultisampleRenderPassTestBase : public TestInstance
153 {
154 public:
155 MultisampleRenderPassTestBase (Context& context, TestConfig config);
156 ~MultisampleRenderPassTestBase (void);
157
158 protected:
159
160 Move<VkImage> createImage (VkSampleCountFlagBits sampleCountBit,
161 VkImageUsageFlags usage) const;
162 Move<VkImage> createImage (VkSampleCountFlagBits sampleCountBit,
163 VkImageUsageFlags usage,
164 deUint32 width,
165 deUint32 height,
166 deUint32 mipLevels) const;
167 vector<VkImageSp> createImages (VkSampleCountFlagBits sampleCountBit,
168 VkImageUsageFlags usage) const;
169 vector<VkImageSp> createImages (VkSampleCountFlagBits sampleCountBit,
170 VkImageUsageFlags usage,
171 deUint32 width,
172 deUint32 height,
173 deUint32 mipLevels) const;
174 vector<AllocationSp> createImageMemory (const vector<VkImageSp>& images) const;
175 vector<VkImageViewSp> createImageViews (const vector<VkImageSp>& images,
176 deUint32 mipLevel = 0) const;
177
178 vector<VkBufferSp> createBuffers () const;
179 vector<VkBufferSp> createBuffers (deUint32 width,
180 deUint32 height,
181 deUint32 mipLevels) const;
182 vector<AllocationSp> createBufferMemory (const vector<VkBufferSp>& buffers) const;
183
184 Move<VkFramebuffer> createFramebuffer (const std::vector<VkImageViewSp> multisampleImageViews,
185 const std::vector<VkImageViewSp> singlesampleImageViews,
186 VkRenderPass renderPass) const;
187
188 void clearAttachments (VkCommandBuffer commandBuffer) const;
189 VkDeviceSize getPixelSize () const;
190 tcu::Vec4 getFormatThreshold () const;
191 VkSampleCountFlagBits sampleCountBitFromSampleCount (deUint32 count) const;
192 void logImage (const std::string& name,
193 const tcu::ConstPixelBufferAccess& image) const;
194
195 protected:
196
197 const bool m_testCompatibility;
198 const SharedGroupParams m_groupParams;
199
200 const VkFormat m_format;
201 const VkSampleCountFlagBits m_sampleCount;
202 const deUint32 m_layerCount;
203 const deUint32 m_attachmentsCount;
204 const deUint32 m_width;
205 const deUint32 m_height;
206 };
207
MultisampleRenderPassTestBase(Context& context, TestConfig config)208 MultisampleRenderPassTestBase::MultisampleRenderPassTestBase (Context& context, TestConfig config)
209 : TestInstance (context)
210 , m_testCompatibility (config.testType == COMPATIBILITY)
211 , m_groupParams (config.groupParams)
212 , m_format (config.format)
213 , m_sampleCount (sampleCountBitFromSampleCount(config.sampleCount))
214 , m_layerCount (config.layerCount)
215 , m_attachmentsCount (config.attachmentCount)
216 , m_width (config.width)
217 , m_height (config.height)
218 {
219 }
220
~MultisampleRenderPassTestBase()221 MultisampleRenderPassTestBase::~MultisampleRenderPassTestBase ()
222 {
223 }
224
createImage(VkSampleCountFlagBits sampleCountBit, VkImageUsageFlags usage) const225 Move<VkImage> MultisampleRenderPassTestBase::createImage (VkSampleCountFlagBits sampleCountBit, VkImageUsageFlags usage) const
226 {
227 return createImage(sampleCountBit, usage, m_width, m_height, 1u);
228 }
229
createImage(VkSampleCountFlagBits sampleCountBit, VkImageUsageFlags usage, deUint32 width, deUint32 height, deUint32 mipLevels) const230 Move<VkImage> MultisampleRenderPassTestBase::createImage (VkSampleCountFlagBits sampleCountBit,
231 VkImageUsageFlags usage,
232 deUint32 width,
233 deUint32 height,
234 deUint32 mipLevels) const
235 {
236 const InstanceInterface& vki = m_context.getInstanceInterface();
237 const DeviceInterface& vkd = m_context.getDeviceInterface();
238 VkDevice device = m_context.getDevice();
239 VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
240 const tcu::TextureFormat format (mapVkFormat(m_format));
241 const VkImageType imageType (VK_IMAGE_TYPE_2D);
242 const VkImageTiling imageTiling (VK_IMAGE_TILING_OPTIMAL);
243 const VkFormatProperties formatProperties (getPhysicalDeviceFormatProperties(vki, physicalDevice, m_format));
244 const VkExtent3D imageExtent =
245 {
246 width,
247 height,
248 1u
249 };
250
251 try
252 {
253 const VkImageFormatProperties imageFormatProperties(getPhysicalDeviceImageFormatProperties(vki, physicalDevice, m_format, imageType, imageTiling, usage, 0u));
254
255 if ((tcu::hasDepthComponent(format.order) || tcu::hasStencilComponent(format.order))
256 && (formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) == 0)
257 TCU_THROW(NotSupportedError, "Format can't be used as depth stencil attachment");
258
259 if (!(tcu::hasDepthComponent(format.order) || tcu::hasStencilComponent(format.order))
260 && (formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) == 0)
261 TCU_THROW(NotSupportedError, "Format can't be used as color attachment");
262
263 if (imageFormatProperties.maxExtent.width < imageExtent.width
264 || imageFormatProperties.maxExtent.height < imageExtent.height
265 || ((imageFormatProperties.sampleCounts & m_sampleCount) == 0)
266 || imageFormatProperties.maxArrayLayers < m_layerCount)
267 {
268 TCU_THROW(NotSupportedError, "Image type not supported");
269 }
270
271 const VkImageCreateInfo pCreateInfo =
272 {
273 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
274 DE_NULL,
275 0u,
276 imageType,
277 m_format,
278 imageExtent,
279 mipLevels,
280 m_layerCount,
281 sampleCountBit,
282 imageTiling,
283 usage,
284 VK_SHARING_MODE_EXCLUSIVE,
285 0u,
286 DE_NULL,
287 VK_IMAGE_LAYOUT_UNDEFINED
288 };
289
290 return ::createImage(vkd, device, &pCreateInfo);
291 }
292 catch (const vk::Error& error)
293 {
294 if (error.getError() == VK_ERROR_FORMAT_NOT_SUPPORTED)
295 TCU_THROW(NotSupportedError, "Image format not supported");
296
297 throw;
298 }
299 }
300
createImages(VkSampleCountFlagBits sampleCountBit, VkImageUsageFlags usage) const301 vector<VkImageSp> MultisampleRenderPassTestBase::createImages (VkSampleCountFlagBits sampleCountBit, VkImageUsageFlags usage) const
302 {
303 std::vector<VkImageSp> images (m_attachmentsCount);
304 for (size_t imageNdx = 0; imageNdx < m_attachmentsCount; imageNdx++)
305 images[imageNdx] = safeSharedPtr(new Unique<VkImage>(createImage(sampleCountBit, usage)));
306 return images;
307 }
308
createImages(VkSampleCountFlagBits sampleCountBit, VkImageUsageFlags usage, deUint32 width, deUint32 height, deUint32 mipLevels) const309 vector<VkImageSp> MultisampleRenderPassTestBase::createImages (VkSampleCountFlagBits sampleCountBit,
310 VkImageUsageFlags usage,
311 deUint32 width,
312 deUint32 height,
313 deUint32 mipLevels) const
314 {
315 std::vector<VkImageSp> images (m_attachmentsCount);
316 for (size_t imageNdx = 0; imageNdx < m_attachmentsCount; imageNdx++)
317 images[imageNdx] = safeSharedPtr(new Unique<VkImage>(createImage(sampleCountBit, usage, width, height, mipLevels)));
318 return images;
319 }
320
createImageMemory(const vector<VkImageSp>& images) const321 vector<AllocationSp> MultisampleRenderPassTestBase::createImageMemory (const vector<VkImageSp>& images) const
322 {
323 const DeviceInterface& vkd = m_context.getDeviceInterface();
324 VkDevice device = m_context.getDevice();
325 Allocator& allocator = m_context.getDefaultAllocator();
326 std::vector<AllocationSp> memory (images.size());
327
328 for (size_t memoryNdx = 0; memoryNdx < memory.size(); memoryNdx++)
329 {
330 VkImage image = **images[memoryNdx];
331 VkMemoryRequirements requirements = getImageMemoryRequirements(vkd, device, image);
332
333 de::MovePtr<Allocation> allocation (allocator.allocate(requirements, MemoryRequirement::Any));
334 VK_CHECK(vkd.bindImageMemory(device, image, allocation->getMemory(), allocation->getOffset()));
335 memory[memoryNdx] = safeSharedPtr(allocation.release());
336 }
337 return memory;
338 }
339
createImageViews(const vector<VkImageSp>& images, deUint32 mipLevel) const340 vector<VkImageViewSp> MultisampleRenderPassTestBase::createImageViews (const vector<VkImageSp>& images, deUint32 mipLevel) const
341 {
342 const DeviceInterface& vkd = m_context.getDeviceInterface();
343 VkDevice device = m_context.getDevice();
344 std::vector<VkImageViewSp> views (images.size());
345 const VkImageSubresourceRange range =
346 {
347 VK_IMAGE_ASPECT_COLOR_BIT,
348 mipLevel,
349 1u,
350 0u,
351 m_layerCount
352 };
353
354 for (size_t imageNdx = 0; imageNdx < images.size(); imageNdx++)
355 {
356 const VkImageViewCreateInfo pCreateInfo =
357 {
358 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
359 DE_NULL,
360 0u,
361 **images[imageNdx],
362 VK_IMAGE_VIEW_TYPE_2D_ARRAY,
363 m_format,
364 makeComponentMappingRGBA(),
365 range,
366 };
367 views[imageNdx] = safeSharedPtr(new Unique<VkImageView>(createImageView(vkd, device, &pCreateInfo)));
368 }
369
370 return views;
371 }
372
createBuffers() const373 vector<VkBufferSp> MultisampleRenderPassTestBase::createBuffers () const
374 {
375 return createBuffers(m_width, m_height, 1u);
376 }
377
createBuffers(deUint32 width, deUint32 height, deUint32 mipLevels) const378 vector<VkBufferSp> MultisampleRenderPassTestBase::createBuffers (deUint32 width, deUint32 height, deUint32 mipLevels) const
379 {
380 DE_ASSERT(mipLevels);
381
382 VkDeviceSize size = 0;
383 for (deUint32 level = 0; level < mipLevels; ++level)
384 {
385 DE_ASSERT(width && height);
386
387 size += (width * height);
388 height /= 2;
389 width /=2;
390 }
391
392 const DeviceInterface& vkd = m_context.getDeviceInterface();
393 VkDevice device = m_context.getDevice();
394 std::vector<VkBufferSp> buffers (m_attachmentsCount);
395 const VkDeviceSize pixelSize (getPixelSize());
396 const VkBufferCreateInfo createInfo =
397 {
398 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
399 DE_NULL,
400 0u,
401
402 size * m_layerCount * pixelSize,
403 VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
404
405 VK_SHARING_MODE_EXCLUSIVE,
406 0u,
407 DE_NULL
408 };
409
410 for (size_t bufferNdx = 0; bufferNdx < buffers.size(); bufferNdx++)
411 buffers[bufferNdx] = safeSharedPtr(new Unique<VkBuffer>(createBuffer(vkd, device, &createInfo)));
412
413 return buffers;
414 }
415
createBufferMemory(const vector<VkBufferSp>& buffers) const416 vector<AllocationSp> MultisampleRenderPassTestBase::createBufferMemory (const vector<VkBufferSp>& buffers) const
417 {
418 const DeviceInterface& vkd = m_context.getDeviceInterface();
419 VkDevice device = m_context.getDevice();
420 Allocator& allocator = m_context.getDefaultAllocator();
421 std::vector<de::SharedPtr<Allocation> > memory (buffers.size());
422
423 for (size_t memoryNdx = 0; memoryNdx < memory.size(); memoryNdx++)
424 {
425 VkBuffer buffer = **buffers[memoryNdx];
426 VkMemoryRequirements requirements = getBufferMemoryRequirements(vkd, device, buffer);
427 de::MovePtr<Allocation> allocation (allocator.allocate(requirements, MemoryRequirement::HostVisible));
428
429 VK_CHECK(vkd.bindBufferMemory(device, buffer, allocation->getMemory(), allocation->getOffset()));
430 memory[memoryNdx] = safeSharedPtr(allocation.release());
431 }
432 return memory;
433 }
434
createFramebuffer(const std::vector<VkImageViewSp> multisampleImageViews, const std::vector<VkImageViewSp> singlesampleImageViews, VkRenderPass renderPass) const435 Move<VkFramebuffer> MultisampleRenderPassTestBase::createFramebuffer (const std::vector<VkImageViewSp> multisampleImageViews,
436 const std::vector<VkImageViewSp> singlesampleImageViews,
437 VkRenderPass renderPass) const
438 {
439 // when RenderPass was not created then we are testing dynamic rendering
440 // and we can't create framebuffer without valid RenderPass object
441 if (!renderPass)
442 return Move<VkFramebuffer>();
443
444 const DeviceInterface& vkd = m_context.getDeviceInterface();
445 VkDevice device = m_context.getDevice();
446
447 std::vector<VkImageView> attachments;
448 attachments.reserve(multisampleImageViews.size() + singlesampleImageViews.size());
449
450 DE_ASSERT(multisampleImageViews.size() == singlesampleImageViews.size());
451
452 for (size_t ndx = 0; ndx < multisampleImageViews.size(); ndx++)
453 {
454 attachments.push_back(**multisampleImageViews[ndx]);
455 attachments.push_back(**singlesampleImageViews[ndx]);
456 }
457
458 const VkFramebufferCreateInfo createInfo =
459 {
460 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
461 DE_NULL,
462 0u,
463
464 renderPass,
465 (deUint32)attachments.size(),
466 &attachments[0],
467
468 m_width,
469 m_height,
470 m_layerCount
471 };
472
473 return ::createFramebuffer(vkd, device, &createInfo);
474 }
475
clearAttachments(VkCommandBuffer commandBuffer) const476 void MultisampleRenderPassTestBase::clearAttachments (VkCommandBuffer commandBuffer) const
477 {
478 const DeviceInterface& vkd = m_context.getDeviceInterface();
479 const tcu::TextureFormat format (mapVkFormat(m_format));
480 const tcu::TextureChannelClass channelClass (tcu::getTextureChannelClass(format.type));
481 VkClearValue value;
482
483 // Clear everything to black
484 switch (channelClass)
485 {
486 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
487 value = makeClearValueColorF32(-1.0f, -1.0f, -1.0f, -1.0f);
488 break;
489
490 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
491 value = makeClearValueColorF32(0.0f, 0.0f, 0.0f, 0.0f);
492 break;
493
494 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
495 value = makeClearValueColorF32(-1.0f, -1.0f, -1.0f, -1.0f);
496 break;
497
498 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
499 value = makeClearValueColorI32(-128, -128, -128, -128);
500 break;
501
502 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
503 value = makeClearValueColorU32(0u, 0u, 0u, 0u);
504 break;
505
506 default:
507 DE_FATAL("Unknown channel class");
508 }
509 std::vector<VkClearAttachment> colors(m_attachmentsCount);
510 for (deUint32 attachmentNdx = 0; attachmentNdx < m_attachmentsCount; attachmentNdx++)
511 {
512 colors[attachmentNdx].aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
513 colors[attachmentNdx].colorAttachment = attachmentNdx;
514 colors[attachmentNdx].clearValue = value;
515 }
516 const VkClearRect rect =
517 {
518 {
519 { 0u, 0u },
520 { m_width, m_height }
521 },
522 0u,
523 m_layerCount,
524 };
525 vkd.cmdClearAttachments(commandBuffer, deUint32(colors.size()), &colors[0], 1u, &rect);
526 }
527
getPixelSize() const528 VkDeviceSize MultisampleRenderPassTestBase::getPixelSize () const
529 {
530 const tcu::TextureFormat format(mapVkFormat(m_format));
531 return format.getPixelSize();
532 }
533
getFormatThreshold() const534 tcu::Vec4 MultisampleRenderPassTestBase::getFormatThreshold () const
535 {
536 const tcu::TextureFormat tcuFormat (mapVkFormat(m_format));
537 const deUint32 componentCount (tcu::getNumUsedChannels(tcuFormat.order));
538
539 if (isSnormFormat(m_format))
540 {
541 return Vec4((componentCount >= 1) ? 1.5f * getRepresentableDiffSnorm(m_format, 0) : 0.0f,
542 (componentCount >= 2) ? 1.5f * getRepresentableDiffSnorm(m_format, 1) : 0.0f,
543 (componentCount >= 3) ? 1.5f * getRepresentableDiffSnorm(m_format, 2) : 0.0f,
544 (componentCount == 4) ? 1.5f * getRepresentableDiffSnorm(m_format, 3) : 0.0f);
545 }
546 else if (isUnormFormat(m_format))
547 {
548 return Vec4((componentCount >= 1) ? 1.5f * getRepresentableDiffUnorm(m_format, 0) : 0.0f,
549 (componentCount >= 2) ? 1.5f * getRepresentableDiffUnorm(m_format, 1) : 0.0f,
550 (componentCount >= 3) ? 1.5f * getRepresentableDiffUnorm(m_format, 2) : 0.0f,
551 (componentCount == 4) ? 1.5f * getRepresentableDiffUnorm(m_format, 3) : 0.0f);
552 }
553 else if (isFloatFormat(m_format))
554 {
555 return (tcuFormat.type == tcu::TextureFormat::HALF_FLOAT) ? tcu::Vec4(0.005f) : Vec4(0.00001f);
556 }
557 else
558 return Vec4(0.001f);
559 }
560
sampleCountBitFromSampleCount(deUint32 count) const561 VkSampleCountFlagBits MultisampleRenderPassTestBase::sampleCountBitFromSampleCount (deUint32 count) const
562 {
563 switch (count)
564 {
565 case 1: return VK_SAMPLE_COUNT_1_BIT;
566 case 2: return VK_SAMPLE_COUNT_2_BIT;
567 case 4: return VK_SAMPLE_COUNT_4_BIT;
568 case 8: return VK_SAMPLE_COUNT_8_BIT;
569 case 16: return VK_SAMPLE_COUNT_16_BIT;
570 case 32: return VK_SAMPLE_COUNT_32_BIT;
571 case 64: return VK_SAMPLE_COUNT_64_BIT;
572
573 default:
574 DE_FATAL("Invalid sample count");
575 return (VkSampleCountFlagBits)0x0;
576 }
577 }
578
logImage(const std::string& name, const tcu::ConstPixelBufferAccess& image) const579 void MultisampleRenderPassTestBase::logImage (const std::string& name, const tcu::ConstPixelBufferAccess& image) const
580 {
581 m_context.getTestContext().getLog() << tcu::LogImage(name.c_str(), name.c_str(), image);
582
583 for (deUint32 layerNdx = 0; layerNdx < m_layerCount; ++layerNdx)
584 {
585 const std::string layerName (name + " Layer:" + de::toString(layerNdx));
586 tcu::ConstPixelBufferAccess layerImage (image.getFormat(), m_width, m_height, 1, image.getPixelPtr(0, 0, layerNdx));
587
588 m_context.getTestContext().getLog() << tcu::LogImage(layerName.c_str(), layerName.c_str(), layerImage);
589 }
590 }
591
592 class MultisampleRenderPassTestInstance : public MultisampleRenderPassTestBase
593 {
594 public:
595 MultisampleRenderPassTestInstance (Context& context, TestConfig config);
596 ~MultisampleRenderPassTestInstance (void);
597
598 tcu::TestStatus iterate (void);
599
600 private:
601
602 void drawCommands (VkCommandBuffer cmdBuffer, VkPipeline pipeline, VkPipelineLayout pipelineLayout) const;
603
604 template<typename RenderpassSubpass>
605 void submit (void);
606 void submitDynamicRendering (void);
607 void submitSwitch (const SharedGroupParams groupParams);
608 void verify (void);
609
610 template<typename RenderPassTrait>
611 Move<VkRenderPass> createRenderPass (bool usedResolveAttachment);
612 Move<VkRenderPass> createRenderPassSwitch (bool usedResolveAttachment);
613 Move<VkRenderPass> createRenderPassCompatible (void);
614 Move<VkPipelineLayout> createRenderPipelineLayout (void);
615 Move<VkPipeline> createRenderPipeline (void);
616
617 #ifndef CTS_USES_VULKANSC
618 void beginSecondaryCmdBuffer (VkCommandBuffer cmdBuffer, VkRenderingFlagsKHR renderingFlags = 0u) const;
619 #endif // CTS_USES_VULKANSC
620
621 private:
622
623 const std::vector<VkImageSp> m_multisampleImages;
624 const std::vector<AllocationSp> m_multisampleImageMemory;
625 const std::vector<VkImageViewSp> m_multisampleImageViews;
626
627 const std::vector<VkImageSp> m_singlesampleImages;
628 const std::vector<AllocationSp> m_singlesampleImageMemory;
629 const std::vector<VkImageViewSp> m_singlesampleImageViews;
630
631 const Unique<VkRenderPass> m_renderPass;
632 const Unique<VkRenderPass> m_renderPassCompatible;
633 const Unique<VkFramebuffer> m_framebuffer;
634
635 const Unique<VkPipelineLayout> m_renderPipelineLayout;
636 const Unique<VkPipeline> m_renderPipeline;
637
638 const std::vector<VkBufferSp> m_buffers;
639 const std::vector<AllocationSp> m_bufferMemory;
640
641 const Unique<VkCommandPool> m_commandPool;
642 tcu::TextureLevel m_sum;
643 tcu::TextureLevel m_sumSrgb;
644 deUint32 m_sampleMask;
645 tcu::ResultCollector m_resultCollector;
646
647 protected:
648 MultisampleRenderPassTestInstance (Context& context, TestConfig config, deUint32 renderLevel);
649
650 const deUint32 m_renderLevel;
651 };
652
MultisampleRenderPassTestInstance(Context& context, TestConfig config)653 MultisampleRenderPassTestInstance::MultisampleRenderPassTestInstance (Context& context, TestConfig config)
654 : MultisampleRenderPassTestInstance (context, config, /*defaulf render level*/0u)
655 {
656 }
657
MultisampleRenderPassTestInstance(Context& context, TestConfig config, deUint32 renderLevel)658 MultisampleRenderPassTestInstance::MultisampleRenderPassTestInstance (Context& context, TestConfig config, deUint32 renderLevel)
659 : MultisampleRenderPassTestBase(context, config)
660
661 , m_multisampleImages (createImages(m_sampleCount, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT))
662 , m_multisampleImageMemory (createImageMemory(m_multisampleImages))
663 , m_multisampleImageViews (createImageViews(m_multisampleImages))
664
665 , m_singlesampleImages (createImages(VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, (1u << renderLevel)*m_width, (1u << renderLevel)*m_height, renderLevel+1 ))
666 , m_singlesampleImageMemory (createImageMemory(m_singlesampleImages))
667 , m_singlesampleImageViews (createImageViews(m_singlesampleImages, renderLevel))
668
669 // The "normal" render pass has an unused resolve attachment when testing compatibility.
670 , m_renderPass (createRenderPassSwitch(!m_testCompatibility))
671 , m_renderPassCompatible (createRenderPassCompatible())
672 , m_framebuffer (createFramebuffer(m_multisampleImageViews, m_singlesampleImageViews, *m_renderPass))
673
674 , m_renderPipelineLayout (createRenderPipelineLayout())
675 , m_renderPipeline (createRenderPipeline())
676
677 , m_buffers (createBuffers((1u << renderLevel)*m_width, (1u << renderLevel)*m_height, renderLevel+1 ))
678 , m_bufferMemory (createBufferMemory(m_buffers))
679
680 , m_commandPool (createCommandPool(context.getDeviceInterface(), context.getDevice(), VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, context.getUniversalQueueFamilyIndex()))
681 , m_sum (tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT), m_width, m_height, m_layerCount)
682 , m_sumSrgb (tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT), m_width, m_height, m_layerCount)
683 , m_sampleMask (0x0u)
684
685 , m_renderLevel (renderLevel)
686 {
687 tcu::clear(m_sum.getAccess(), Vec4(0.0f, 0.0f, 0.0f, 0.0f));
688 tcu::clear(m_sumSrgb.getAccess(), Vec4(0.0f, 0.0f, 0.0f, 0.0f));
689 }
690
~MultisampleRenderPassTestInstance(void)691 MultisampleRenderPassTestInstance::~MultisampleRenderPassTestInstance (void)
692 {
693 }
694
drawCommands(VkCommandBuffer cmdBuffer, VkPipeline pipeline, VkPipelineLayout pipelineLayout) const695 void MultisampleRenderPassTestInstance::drawCommands(VkCommandBuffer cmdBuffer, VkPipeline pipeline, VkPipelineLayout pipelineLayout) const
696 {
697 const DeviceInterface& vkd = m_context.getDeviceInterface();
698
699 // Clear everything to black
700 clearAttachments(cmdBuffer);
701
702 // Render black samples
703 vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
704 vkd.cmdPushConstants(cmdBuffer, pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0u, sizeof(m_sampleMask), &m_sampleMask);
705 vkd.cmdDraw(cmdBuffer, 6u, 1u, 0u, 0u);
706 }
707
708 template<typename RenderpassSubpass>
submit(void)709 void MultisampleRenderPassTestInstance::submit (void)
710 {
711 const DeviceInterface& vkd (m_context.getDeviceInterface());
712 const VkDevice device (m_context.getDevice());
713 const Unique<VkCommandBuffer> commandBuffer (allocateCommandBuffer(vkd, device, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
714
715 beginCommandBuffer(vkd, *commandBuffer);
716
717 // Memory barriers between previous copies and rendering
718 {
719 std::vector<VkImageMemoryBarrier> barriers;
720
721 for (size_t dstNdx = 0; dstNdx < m_singlesampleImages.size(); dstNdx++)
722 {
723 const VkImageMemoryBarrier barrier =
724 {
725 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
726 DE_NULL,
727
728 VK_ACCESS_TRANSFER_READ_BIT,
729 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
730
731 VK_IMAGE_LAYOUT_UNDEFINED,
732 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
733
734 VK_QUEUE_FAMILY_IGNORED,
735 VK_QUEUE_FAMILY_IGNORED,
736
737 **m_singlesampleImages[dstNdx],
738 {
739 VK_IMAGE_ASPECT_COLOR_BIT,
740 m_renderLevel,
741 1u,
742 0u,
743 m_layerCount
744 }
745 };
746
747 barriers.push_back(barrier);
748 }
749
750 vkd.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, (deUint32)barriers.size(), &barriers[0]);
751 }
752
753 VkRect2D renderArea = makeRect2D(m_width, m_height);
754 const typename RenderpassSubpass::SubpassBeginInfo subpassBeginInfo(DE_NULL, VK_SUBPASS_CONTENTS_INLINE);
755 const VkRenderPassBeginInfo beginInfo =
756 {
757 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
758 DE_NULL,
759
760 m_testCompatibility ? *m_renderPassCompatible : *m_renderPass,
761 *m_framebuffer,
762 renderArea,
763
764 0u,
765 DE_NULL
766 };
767 RenderpassSubpass::cmdBeginRenderPass(vkd, *commandBuffer, &beginInfo, &subpassBeginInfo);
768
769 drawCommands(*commandBuffer, *m_renderPipeline, *m_renderPipelineLayout);
770
771 const typename RenderpassSubpass::SubpassEndInfo subpassEndInfo(DE_NULL);
772 RenderpassSubpass::cmdEndRenderPass(vkd, *commandBuffer, &subpassEndInfo);
773
774 for (size_t dstNdx = 0; dstNdx < m_singlesampleImages.size(); dstNdx++)
775 {
776 // assume that buffer(s) have enough memory to store desired amount of mipmaps
777 copyImageToBuffer(vkd, *commandBuffer, **m_singlesampleImages[dstNdx], **m_buffers[dstNdx],
778 m_format, tcu::IVec2((1u << m_renderLevel)*m_width, (1u << m_renderLevel)*m_height), m_renderLevel,
779 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, m_layerCount);
780 }
781
782 endCommandBuffer(vkd, *commandBuffer);
783
784 submitCommandsAndWait(vkd, device, m_context.getUniversalQueue(), *commandBuffer);
785
786 for (size_t memoryBufferNdx = 0; memoryBufferNdx < m_bufferMemory.size(); memoryBufferNdx++)
787 invalidateMappedMemoryRange(vkd, device, m_bufferMemory[memoryBufferNdx]->getMemory(), 0u, VK_WHOLE_SIZE);
788 }
789
submitDynamicRendering(void)790 void MultisampleRenderPassTestInstance::submitDynamicRendering (void)
791 {
792 #ifndef CTS_USES_VULKANSC
793
794 const DeviceInterface& vkd (m_context.getDeviceInterface());
795 const VkDevice device (m_context.getDevice());
796 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer(vkd, device, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
797 Move<VkCommandBuffer> secCmdBuffer;
798
799 // Memory barriers between previous copies and rendering
800 std::vector<VkImageMemoryBarrier> singlesampleImageBarriers(m_singlesampleImages.size(),
801 {
802 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
803 DE_NULL,
804
805 VK_ACCESS_TRANSFER_READ_BIT,
806 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
807
808 VK_IMAGE_LAYOUT_UNDEFINED,
809 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
810
811 VK_QUEUE_FAMILY_IGNORED,
812 VK_QUEUE_FAMILY_IGNORED,
813
814 DE_NULL,
815 {
816 VK_IMAGE_ASPECT_COLOR_BIT,
817 m_renderLevel,
818 1u,
819 0u,
820 m_layerCount
821 }
822 });
823 for (size_t dstNdx = 0; dstNdx < m_singlesampleImages.size(); dstNdx++)
824 singlesampleImageBarriers[dstNdx].image = **m_singlesampleImages[dstNdx];
825
826 // Memory barriers to set multisample image layout to COLOR_ATTACHMENT_OPTIMAL
827 std::vector<VkImageMemoryBarrier> multisampleImageBarriers(m_multisampleImages.size(),
828 {
829 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
830 DE_NULL,
831
832 0,
833 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
834
835 VK_IMAGE_LAYOUT_UNDEFINED,
836 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
837
838 VK_QUEUE_FAMILY_IGNORED,
839 VK_QUEUE_FAMILY_IGNORED,
840
841 DE_NULL,
842 {
843 VK_IMAGE_ASPECT_COLOR_BIT,
844 0u,
845 1u,
846 0u,
847 m_layerCount
848 }
849 });
850 for (size_t dstNdx = 0; dstNdx < m_multisampleImages.size(); dstNdx++)
851 multisampleImageBarriers[dstNdx].image = **m_multisampleImages[dstNdx];
852
853 VkRect2D renderArea = makeRect2D(m_width, m_height);
854 const VkClearValue clearValue = makeClearValueColor( { 0.0f, 0.0f, 0.0f, 1.0f } );
855 std::vector<vk::VkRenderingAttachmentInfoKHR> colorAttachments(m_attachmentsCount,
856 {
857 vk::VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR, // VkStructureType sType;
858 DE_NULL, // const void* pNext;
859 DE_NULL, // VkImageView imageView;
860 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout imageLayout;
861 vk::VK_RESOLVE_MODE_NONE, // VkResolveModeFlagBits resolveMode;
862 DE_NULL, // VkImageView resolveImageView;
863 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout resolveImageLayout;
864 vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp loadOp;
865 vk::VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp storeOp;
866 clearValue // VkClearValue clearValue;
867 });
868
869 for (deUint32 i = 0; i < m_attachmentsCount; ++i)
870 {
871 colorAttachments[i].imageView = **m_multisampleImageViews[i];
872 colorAttachments[i].resolveImageView = **m_singlesampleImageViews[i];
873 if (isIntFormat(m_format) || isUintFormat(m_format))
874 colorAttachments[i].resolveMode = vk::VK_RESOLVE_MODE_SAMPLE_ZERO_BIT;
875 else
876 colorAttachments[i].resolveMode = vk::VK_RESOLVE_MODE_AVERAGE_BIT;
877 }
878
879 vk::VkRenderingInfoKHR renderingInfo
880 {
881 vk::VK_STRUCTURE_TYPE_RENDERING_INFO_KHR,
882 DE_NULL,
883 0, // VkRenderingFlagsKHR flags;
884 renderArea, // VkRect2D renderArea;
885 m_layerCount, // deUint32 layerCount;
886 0u, // deUint32 viewMask;
887 m_attachmentsCount, // deUint32 colorAttachmentCount;
888 colorAttachments.data(), // const VkRenderingAttachmentInfoKHR* pColorAttachments;
889 DE_NULL, // const VkRenderingAttachmentInfoKHR* pDepthAttachment;
890 DE_NULL, // const VkRenderingAttachmentInfoKHR* pStencilAttachment;
891 };
892
893 if (m_groupParams->useSecondaryCmdBuffer)
894 {
895 secCmdBuffer = allocateCommandBuffer(vkd, device, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
896
897 // record secondary command buffer
898 if (m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
899 {
900 beginSecondaryCmdBuffer(*secCmdBuffer, VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
901 vkd.cmdBeginRendering(*secCmdBuffer, &renderingInfo);
902 }
903 else
904 beginSecondaryCmdBuffer(*secCmdBuffer);
905
906 drawCommands(*secCmdBuffer, *m_renderPipeline, *m_renderPipelineLayout);
907
908 if (m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
909 vkd.cmdEndRendering(*secCmdBuffer);
910
911 endCommandBuffer(vkd, *secCmdBuffer);
912
913 // record primary command buffer
914 beginCommandBuffer(vkd, *cmdBuffer);
915
916 vkd.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, (deUint32)singlesampleImageBarriers.size(), &singlesampleImageBarriers[0]);
917 vkd.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, (deUint32)multisampleImageBarriers.size(), &multisampleImageBarriers[0]);
918
919 if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
920 {
921 renderingInfo.flags = vk::VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS;
922 vkd.cmdBeginRendering(*cmdBuffer, &renderingInfo);
923 }
924 vkd.cmdExecuteCommands(*cmdBuffer, 1u, &*secCmdBuffer);
925
926 if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
927 vkd.cmdEndRendering(*cmdBuffer);
928 }
929 else
930 {
931 beginCommandBuffer(vkd, *cmdBuffer);
932
933 vkd.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, (deUint32)singlesampleImageBarriers.size(), &singlesampleImageBarriers[0]);
934 vkd.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, (deUint32)multisampleImageBarriers.size(), &multisampleImageBarriers[0]);
935
936 vkd.cmdBeginRendering(*cmdBuffer, &renderingInfo);
937 drawCommands(*cmdBuffer, *m_renderPipeline, *m_renderPipelineLayout);
938 vkd.cmdEndRendering(*cmdBuffer);
939 }
940
941 // Memory barriers to set single-sample image layout to TRANSFER_SRC_OPTIMAL
942 {
943 std::vector<VkImageMemoryBarrier> barriers;
944
945 for (size_t dstNdx = 0; dstNdx < m_singlesampleImages.size(); dstNdx++)
946 {
947 const VkImageMemoryBarrier barrier =
948 {
949 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
950 DE_NULL,
951
952 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
953 VK_ACCESS_TRANSFER_READ_BIT,
954
955 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
956 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
957
958 VK_QUEUE_FAMILY_IGNORED,
959 VK_QUEUE_FAMILY_IGNORED,
960
961 **m_singlesampleImages[dstNdx],
962 {
963 VK_IMAGE_ASPECT_COLOR_BIT,
964 m_renderLevel,
965 1u,
966 0u,
967 m_layerCount
968 }
969 };
970
971 barriers.push_back(barrier);
972 }
973
974 vkd.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, (deUint32)barriers.size(), &barriers[0]);
975 }
976
977 for (size_t dstNdx = 0; dstNdx < m_singlesampleImages.size(); dstNdx++)
978 {
979 // assume that buffer(s) have enough memory to store desired amount of mipmaps
980 copyImageToBuffer(vkd, *cmdBuffer, **m_singlesampleImages[dstNdx], **m_buffers[dstNdx],
981 m_format, tcu::IVec2((1u << m_renderLevel)*m_width, (1u << m_renderLevel)*m_height), m_renderLevel,
982 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, m_layerCount);
983 }
984
985 endCommandBuffer(vkd, *cmdBuffer);
986
987 submitCommandsAndWait(vkd, device, m_context.getUniversalQueue(), *cmdBuffer);
988
989 for (size_t memoryBufferNdx = 0; memoryBufferNdx < m_bufferMemory.size(); memoryBufferNdx++)
990 invalidateMappedMemoryRange(vkd, device, m_bufferMemory[memoryBufferNdx]->getMemory(), 0u, VK_WHOLE_SIZE);
991
992 #endif // CTS_USES_VULKANSC
993 }
994
submitSwitch(const SharedGroupParams groupParams)995 void MultisampleRenderPassTestInstance::submitSwitch (const SharedGroupParams groupParams)
996 {
997 switch (groupParams->renderingType)
998 {
999 case RENDERING_TYPE_RENDERPASS_LEGACY:
1000 submit<RenderpassSubpass1>();
1001 break;
1002 case RENDERING_TYPE_RENDERPASS2:
1003 submit<RenderpassSubpass2>();
1004 break;
1005 case RENDERING_TYPE_DYNAMIC_RENDERING:
1006 submitDynamicRendering();
1007 break;
1008 default:
1009 TCU_THROW(InternalError, "Impossible");
1010 }
1011 }
1012
verify(void)1013 void MultisampleRenderPassTestInstance::verify (void)
1014 {
1015 const Vec4 errorColor (1.0f, 0.0f, 0.0f, 1.0f);
1016 const Vec4 okColor (0.0f, 1.0f, 0.0f, 1.0f);
1017 const tcu::TextureFormat format (mapVkFormat(m_format));
1018 const tcu::TextureChannelClass channelClass (tcu::getTextureChannelClass(format.type));
1019
1020 deUint32 offset (0u);
1021 deUint32 width ((1u << m_renderLevel) * m_width);
1022 deUint32 height ((1u << m_renderLevel) * m_height);
1023 deUint32 pixelSize (static_cast<deUint32>(getPixelSize()));
1024 for (deUint32 level = 0; level < m_renderLevel; ++level)
1025 {
1026 offset += (width * height * pixelSize);
1027 height /= 2;
1028 width /= 2;
1029 }
1030
1031 std::vector<tcu::ConstPixelBufferAccess> accesses;
1032 for (deUint32 attachmentIdx = 0; attachmentIdx < m_attachmentsCount; ++attachmentIdx)
1033 {
1034 void* const ptr = static_cast<deUint8*>(m_bufferMemory[attachmentIdx]->getHostPtr()) + offset;
1035 accesses.push_back(tcu::ConstPixelBufferAccess(format, m_width, m_height, m_layerCount, ptr));
1036 }
1037
1038 tcu::TextureLevel errorMask (tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), m_width, m_height, m_layerCount);
1039 tcu::TestLog& log (m_context.getTestContext().getLog());
1040
1041 switch (channelClass)
1042 {
1043 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
1044 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
1045 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
1046 {
1047 const int componentCount (tcu::getNumUsedChannels(format.order));
1048 bool isOk = true;
1049 float clearValue;
1050 float renderValue;
1051
1052 switch (channelClass)
1053 {
1054 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
1055 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
1056 clearValue = -1.0f;
1057 renderValue = 1.0f;
1058 break;
1059
1060 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
1061 clearValue = 0.0f;
1062 renderValue = 1.0f;
1063 break;
1064
1065 default:
1066 clearValue = 0.0f;
1067 renderValue = 0.0f;
1068 DE_FATAL("Unknown channel class");
1069 }
1070
1071 for (deUint32 z = 0; z < m_layerCount; z++)
1072 for (deUint32 y = 0; y < m_height; y++)
1073 for (deUint32 x = 0; x < m_width; x++)
1074 {
1075 // Color has to be black if no samples were covered, white if all samples were covered or same in every attachment
1076 const Vec4 firstColor (accesses[0].getPixel(x, y, z));
1077 const Vec4 refColor (m_sampleMask == 0x0u
1078 ? Vec4(clearValue,
1079 componentCount > 1 ? clearValue : 0.0f,
1080 componentCount > 2 ? clearValue : 0.0f,
1081 componentCount > 3 ? clearValue : 1.0f)
1082 : m_sampleMask == ((0x1u << m_sampleCount) - 1u)
1083 ? Vec4(renderValue,
1084 componentCount > 1 ? renderValue : 0.0f,
1085 componentCount > 2 ? renderValue : 0.0f,
1086 componentCount > 3 ? renderValue : 1.0f)
1087 : firstColor);
1088
1089 errorMask.getAccess().setPixel(okColor, x, y, z);
1090
1091 for (size_t attachmentNdx = 0; attachmentNdx < m_attachmentsCount; attachmentNdx++)
1092 {
1093 const Vec4 color (accesses[attachmentNdx].getPixel(x, y, z));
1094
1095 if (refColor != color)
1096 {
1097 isOk = false;
1098 errorMask.getAccess().setPixel(errorColor, x, y, z);
1099 break;
1100 }
1101 }
1102
1103 {
1104 const Vec4 old = m_sum.getAccess().getPixel(x, y, z);
1105 m_sum.getAccess().setPixel(old + (tcu::isSRGB(format) ? tcu::sRGBToLinear(firstColor) : firstColor), x, y, z);
1106
1107 const Vec4 oldSrgb = m_sumSrgb.getAccess().getPixel(x, y, z);
1108 m_sumSrgb.getAccess().setPixel(oldSrgb + firstColor, x, y, z);
1109 }
1110 }
1111
1112 if (!isOk)
1113 {
1114 const std::string sectionName ("ResolveVerifyWithMask" + de::toString(m_sampleMask));
1115 const tcu::ScopedLogSection section (log, sectionName, sectionName);
1116
1117 for (size_t attachmentNdx = 0; attachmentNdx < m_attachmentsCount; attachmentNdx++)
1118 logImage(std::string("Attachment") + de::toString(attachmentNdx), accesses[attachmentNdx]);
1119
1120 logImage("ErrorMask", errorMask.getAccess());
1121
1122 if (m_sampleMask == 0x0u)
1123 {
1124 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Empty sample mask didn't produce all " << clearValue << " pixels" << tcu::TestLog::EndMessage;
1125 m_resultCollector.fail("Empty sample mask didn't produce correct pixel values");
1126 }
1127 else if (m_sampleMask == ((0x1u << m_sampleCount) - 1u))
1128 {
1129 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Full sample mask didn't produce all " << renderValue << " pixels" << tcu::TestLog::EndMessage;
1130 m_resultCollector.fail("Full sample mask didn't produce correct pixel values");
1131 }
1132 else
1133 {
1134 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Resolve is inconsistent between attachments" << tcu::TestLog::EndMessage;
1135 m_resultCollector.fail("Resolve is inconsistent between attachments");
1136 }
1137 }
1138 break;
1139 }
1140
1141 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
1142 {
1143 const int componentCount (tcu::getNumUsedChannels(format.order));
1144 const UVec4 bitDepth (tcu::getTextureFormatBitDepth(format).cast<deUint32>());
1145 const UVec4 renderValue (tcu::select((UVec4(1u) << tcu::min(UVec4(8u), bitDepth)) - UVec4(1u),
1146 UVec4(0u, 0u, 0u, 1u),
1147 tcu::lessThan(IVec4(0, 1, 2, 3), IVec4(componentCount))));
1148 const UVec4 clearValue (tcu::select(UVec4(0u),
1149 UVec4(0u, 0u, 0u, 1u),
1150 tcu::lessThan(IVec4(0, 1, 2, 3), IVec4(componentCount))));
1151 bool unexpectedValues = false;
1152 bool inconsistentComponents = false;
1153 bool inconsistentAttachments = false;
1154
1155 for (deUint32 z = 0; z < m_layerCount; z++)
1156 for (deUint32 y = 0; y < m_height; y++)
1157 for (deUint32 x = 0; x < m_width; x++)
1158 {
1159 // Color has to be all zeros if no samples were covered, all 255 if all samples were covered or consistent across all attachments
1160 const UVec4 refColor (m_sampleMask == 0x0u
1161 ? clearValue
1162 : m_sampleMask == ((0x1u << m_sampleCount) - 1u)
1163 ? renderValue
1164 : accesses[0].getPixelUint(x, y, z));
1165 bool isOk = true;
1166
1167 // If reference value was taken from first attachment, check that it is valid value i.e. clear or render value
1168 if (m_sampleMask != 0x0u && m_sampleMask != ((0x1u << m_sampleCount) - 1u))
1169 {
1170 // Each component must be resolved same way
1171 const BVec4 isRenderValue (refColor == renderValue);
1172 const BVec4 isClearValue (refColor == clearValue);
1173 const bool unexpectedValue (tcu::anyNotEqual(tcu::logicalOr(isRenderValue, isClearValue), BVec4(true)));
1174 const bool inconsistentComponent (!(tcu::allEqual(isRenderValue, BVec4(true)) || tcu::allEqual(isClearValue, BVec4(true))));
1175
1176 unexpectedValues |= unexpectedValue;
1177 inconsistentComponents |= inconsistentComponent;
1178
1179 if (unexpectedValue || inconsistentComponent)
1180 isOk = false;
1181 }
1182
1183 for (size_t attachmentNdx = 0; attachmentNdx < m_attachmentsCount; attachmentNdx++)
1184 {
1185 const UVec4 color (accesses[attachmentNdx].getPixelUint(x, y, z));
1186
1187 if (refColor != color)
1188 {
1189 isOk = false;
1190 inconsistentAttachments = true;
1191 break;
1192 }
1193 }
1194
1195 errorMask.getAccess().setPixel((isOk ? okColor : errorColor), x, y, z);
1196 }
1197
1198 if (unexpectedValues || inconsistentComponents || inconsistentAttachments)
1199 {
1200 const std::string sectionName ("ResolveVerifyWithMask" + de::toString(m_sampleMask));
1201 const tcu::ScopedLogSection section (log, sectionName, sectionName);
1202
1203 for (size_t attachmentNdx = 0; attachmentNdx < m_attachmentsCount; attachmentNdx++)
1204 logImage(std::string("Attachment") + de::toString(attachmentNdx), accesses[attachmentNdx]);
1205
1206 logImage("ErrorMask", errorMask.getAccess());
1207
1208 if (m_sampleMask == 0x0u)
1209 {
1210 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Empty sample mask didn't produce all " << clearValue << " pixels" << tcu::TestLog::EndMessage;
1211 m_resultCollector.fail("Empty sample mask didn't produce correct pixels");
1212 }
1213 else if (m_sampleMask == ((0x1u << m_sampleCount) - 1u))
1214 {
1215 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Full sample mask didn't produce all " << renderValue << " pixels" << tcu::TestLog::EndMessage;
1216 m_resultCollector.fail("Full sample mask didn't produce correct pixels");
1217 }
1218 else
1219 {
1220 if (unexpectedValues)
1221 {
1222 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Resolve produced unexpected values i.e. not " << clearValue << " or " << renderValue << tcu::TestLog::EndMessage;
1223 m_resultCollector.fail("Resolve produced unexpected values");
1224 }
1225
1226 if (inconsistentComponents)
1227 {
1228 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Different components of attachment were resolved to different values." << tcu::TestLog::EndMessage;
1229 m_resultCollector.fail("Different components of attachment were resolved to different values.");
1230 }
1231
1232 if (inconsistentAttachments)
1233 {
1234 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Different attachments were resolved to different values." << tcu::TestLog::EndMessage;
1235 m_resultCollector.fail("Different attachments were resolved to different values.");
1236 }
1237 }
1238 }
1239 break;
1240 }
1241
1242 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
1243 {
1244 const int componentCount (tcu::getNumUsedChannels(format.order));
1245 const IVec4 bitDepth (tcu::getTextureFormatBitDepth(format));
1246 const IVec4 renderValue (tcu::select((IVec4(1) << (tcu::min(IVec4(8), bitDepth) - IVec4(1))) - IVec4(1),
1247 IVec4(0, 0, 0, 1),
1248 tcu::lessThan(IVec4(0, 1, 2, 3), IVec4(componentCount))));
1249 const IVec4 clearValue (tcu::select(-(IVec4(1) << (tcu::min(IVec4(8), bitDepth) - IVec4(1))),
1250 IVec4(0, 0, 0, 1),
1251 tcu::lessThan(IVec4(0, 1, 2, 3), IVec4(componentCount))));
1252 bool unexpectedValues = false;
1253 bool inconsistentComponents = false;
1254 bool inconsistentAttachments = false;
1255
1256 for (deUint32 z = 0; z < m_layerCount; z++)
1257 for (deUint32 y = 0; y < m_height; y++)
1258 for (deUint32 x = 0; x < m_width; x++)
1259 {
1260 // Color has to be all zeros if no samples were covered, all 255 if all samples were covered or consistent across all attachments
1261 const IVec4 refColor (m_sampleMask == 0x0u
1262 ? clearValue
1263 : m_sampleMask == ((0x1u << m_sampleCount) - 1u)
1264 ? renderValue
1265 : accesses[0].getPixelInt(x, y, z));
1266 bool isOk = true;
1267
1268 // If reference value was taken from first attachment, check that it is valid value i.e. clear or render value
1269 if (m_sampleMask != 0x0u && m_sampleMask != ((0x1u << m_sampleCount) - 1u))
1270 {
1271 // Each component must be resolved same way
1272 const BVec4 isRenderValue (refColor == renderValue);
1273 const BVec4 isClearValue (refColor == clearValue);
1274 const bool unexpectedValue (tcu::anyNotEqual(tcu::logicalOr(isRenderValue, isClearValue), BVec4(true)));
1275 const bool inconsistentComponent (!(tcu::allEqual(isRenderValue, BVec4(true)) || tcu::allEqual(isClearValue, BVec4(true))));
1276
1277 unexpectedValues |= unexpectedValue;
1278 inconsistentComponents |= inconsistentComponent;
1279
1280 if (unexpectedValue || inconsistentComponent)
1281 isOk = false;
1282 }
1283
1284 for (size_t attachmentNdx = 0; attachmentNdx < m_attachmentsCount; attachmentNdx++)
1285 {
1286 const IVec4 color (accesses[attachmentNdx].getPixelInt(x, y, z));
1287
1288 if (refColor != color)
1289 {
1290 isOk = false;
1291 inconsistentAttachments = true;
1292 break;
1293 }
1294 }
1295
1296 errorMask.getAccess().setPixel((isOk ? okColor : errorColor), x, y, z);
1297 }
1298
1299 if (unexpectedValues || inconsistentComponents || inconsistentAttachments)
1300 {
1301 const std::string sectionName ("ResolveVerifyWithMask" + de::toString(m_sampleMask));
1302 const tcu::ScopedLogSection section (log, sectionName, sectionName);
1303
1304 for (size_t attachmentNdx = 0; attachmentNdx < m_attachmentsCount; attachmentNdx++)
1305 logImage(std::string("Attachment") + de::toString(attachmentNdx), accesses[attachmentNdx]);
1306
1307 logImage("ErrorMask", errorMask.getAccess());
1308
1309 if (m_sampleMask == 0x0u)
1310 {
1311 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Empty sample mask didn't produce all " << clearValue << " pixels" << tcu::TestLog::EndMessage;
1312 m_resultCollector.fail("Empty sample mask didn't produce correct pixels");
1313 }
1314 else if (m_sampleMask == ((0x1u << m_sampleCount) - 1u))
1315 {
1316 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Full sample mask didn't produce all " << renderValue << " pixels" << tcu::TestLog::EndMessage;
1317 m_resultCollector.fail("Full sample mask didn't produce correct pixels");
1318 }
1319 else
1320 {
1321 if (unexpectedValues)
1322 {
1323 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Resolve produced unexpected values i.e. not " << clearValue << " or " << renderValue << tcu::TestLog::EndMessage;
1324 m_resultCollector.fail("Resolve produced unexpected values");
1325 }
1326
1327 if (inconsistentComponents)
1328 {
1329 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Different components of attachment were resolved to different values." << tcu::TestLog::EndMessage;
1330 m_resultCollector.fail("Different components of attachment were resolved to different values.");
1331 }
1332
1333 if (inconsistentAttachments)
1334 {
1335 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Different attachments were resolved to different values." << tcu::TestLog::EndMessage;
1336 m_resultCollector.fail("Different attachments were resolved to different values.");
1337 }
1338 }
1339 }
1340 break;
1341 }
1342
1343 default:
1344 DE_FATAL("Unknown channel class");
1345 }
1346 }
1347
iterate(void)1348 tcu::TestStatus MultisampleRenderPassTestInstance::iterate (void)
1349 {
1350 if (m_sampleMask == 0u)
1351 {
1352 const tcu::TextureFormat format (mapVkFormat(m_format));
1353 const tcu::TextureChannelClass channelClass (tcu::getTextureChannelClass(format.type));
1354 tcu::TestLog& log (m_context.getTestContext().getLog());
1355
1356 switch (channelClass)
1357 {
1358 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
1359 log << TestLog::Message << "Clearing target to zero and rendering 255 pixels with every possible sample mask" << TestLog::EndMessage;
1360 break;
1361
1362 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
1363 log << TestLog::Message << "Clearing target to -128 and rendering 127 pixels with every possible sample mask" << TestLog::EndMessage;
1364 break;
1365
1366 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
1367 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
1368 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
1369 log << TestLog::Message << "Clearing target to black and rendering white pixels with every possible sample mask" << TestLog::EndMessage;
1370 break;
1371
1372 default:
1373 DE_FATAL("Unknown channel class");
1374 }
1375 }
1376
1377 submitSwitch(m_groupParams);
1378 verify();
1379
1380 if (m_sampleMask == ((0x1u << m_sampleCount) - 1u))
1381 {
1382 const tcu::TextureFormat format (mapVkFormat(m_format));
1383 const tcu::TextureChannelClass channelClass (tcu::getTextureChannelClass(format.type));
1384 const Vec4 threshold (getFormatThreshold());
1385 tcu::TestLog& log (m_context.getTestContext().getLog());
1386
1387 if (channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT
1388 || channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT
1389 || channelClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT)
1390 {
1391 const int componentCount (tcu::getNumUsedChannels(format.order));
1392 const Vec4 errorColor (1.0f, 0.0f, 0.0f, 1.0f);
1393 const Vec4 okColor (0.0f, 1.0f, 0.0f, 1.0f);
1394 tcu::TextureLevel errorMask (tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), m_width, m_height, m_layerCount);
1395 bool isOk = true;
1396 Vec4 maxDiff (0.0f);
1397 Vec4 expectedAverage;
1398
1399 switch (channelClass)
1400 {
1401 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
1402 {
1403 expectedAverage = Vec4(0.5f, componentCount > 1 ? 0.5f : 0.0f, componentCount > 2 ? 0.5f : 0.0f, componentCount > 3 ? 0.5f : 1.0f);
1404 break;
1405 }
1406
1407 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
1408 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
1409 {
1410 expectedAverage = Vec4(0.0f, 0.0f, 0.0f, componentCount > 3 ? 0.0f : 1.0f);
1411 break;
1412 }
1413
1414 default:
1415 DE_FATAL("Unknown channel class");
1416 }
1417
1418 for (deUint32 z = 0; z < m_layerCount; z++)
1419 for (deUint32 y = 0; y < m_height; y++)
1420 for (deUint32 x = 0; x < m_width; x++)
1421 {
1422 const Vec4 sum (m_sum.getAccess().getPixel(x, y, z));
1423 const Vec4 average (sum / Vec4((float)(0x1u << m_sampleCount)));
1424 const Vec4 diff (tcu::abs(average - expectedAverage));
1425
1426 m_sum.getAccess().setPixel(average, x, y, z);
1427 errorMask.getAccess().setPixel(okColor, x, y, z);
1428
1429 bool failThreshold;
1430
1431 if (!tcu::isSRGB(format))
1432 {
1433 failThreshold = (diff[0] > threshold.x()
1434 || diff[1] > threshold.y()
1435 || diff[2] > threshold.z()
1436 || diff[3] > threshold.w());
1437 }
1438 else
1439 {
1440 const Vec4 sumSrgb(m_sumSrgb.getAccess().getPixel(x, y, z));
1441 const Vec4 averageSrgb(sumSrgb / Vec4((float)(0x1u << m_sampleCount)));
1442 const Vec4 diffSrgb(tcu::abs(averageSrgb - expectedAverage));
1443
1444 m_sumSrgb.getAccess().setPixel(averageSrgb, x, y, z);
1445
1446 // Spec doesn't restrict implementation to downsample in linear color space. So, comparing both non linear and
1447 // linear diff's in case of srgb formats.
1448 failThreshold = ((diff[0] > threshold.x()
1449 || diff[1] > threshold.y()
1450 || diff[2] > threshold.z()
1451 || diff[3] > threshold.w()) &&
1452 (diffSrgb[0] > threshold.x()
1453 || diffSrgb[1] > threshold.y()
1454 || diffSrgb[2] > threshold.z()
1455 || diffSrgb[3] > threshold.w()));
1456
1457 }
1458
1459 if (failThreshold)
1460 {
1461 isOk = false;
1462 maxDiff = tcu::max(maxDiff, diff);
1463 errorMask.getAccess().setPixel(errorColor, x, y, z);
1464 }
1465 }
1466
1467 log << TestLog::Image("Average resolved values in attachment 0", "Average resolved values in attachment 0", m_sum);
1468
1469 if (!isOk)
1470 {
1471 std::stringstream message;
1472
1473 m_context.getTestContext().getLog() << tcu::LogImage("ErrorMask", "ErrorMask", errorMask.getAccess());
1474
1475 message << "Average resolved values differ from expected average values by more than ";
1476
1477 switch (componentCount)
1478 {
1479 case 1:
1480 message << threshold.x();
1481 break;
1482 case 2:
1483 message << "vec2" << Vec2(threshold.x(), threshold.y());
1484 break;
1485 case 3:
1486 message << "vec3" << Vec3(threshold.x(), threshold.y(), threshold.z());
1487 break;
1488 default:
1489 message << "vec4" << threshold;
1490 }
1491
1492 message << ". Max diff " << maxDiff;
1493 log << TestLog::Message << message.str() << TestLog::EndMessage;
1494
1495 m_resultCollector.fail("Average resolved values differ from expected average values");
1496 }
1497 }
1498
1499 return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage());
1500 }
1501 else
1502 {
1503 m_sampleMask++;
1504 return tcu::TestStatus::incomplete();
1505 }
1506 }
1507
1508 template<typename RenderPassTrait>
createRenderPass(bool usedResolveAttachment)1509 Move<VkRenderPass> MultisampleRenderPassTestInstance::createRenderPass (bool usedResolveAttachment)
1510 {
1511 // make name for RenderPass1Trait or RenderPass2Trait shorter
1512 typedef RenderPassTrait RPT;
1513 typedef typename RPT::AttDesc AttDesc;
1514 typedef typename RPT::AttRef AttRef;
1515 typedef typename RPT::SubpassDesc SubpassDesc;
1516 typedef typename RPT::RenderPassCreateInfo RenderPassCreateInfo;
1517
1518 const DeviceInterface& vkd = m_context.getDeviceInterface();
1519 VkDevice device = m_context.getDevice();
1520 std::vector<AttDesc> attachments;
1521 std::vector<AttRef> colorAttachmentRefs;
1522 std::vector<AttRef> resolveAttachmentRefs;
1523
1524 for (size_t attachmentNdx = 0; attachmentNdx < m_attachmentsCount; attachmentNdx++)
1525 {
1526 {
1527 const AttDesc multisampleAttachment
1528 (
1529 // sType
1530 DE_NULL, // pNext
1531 0u, // flags
1532 m_format, // format
1533 m_sampleCount, // samples
1534 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // loadOp
1535 VK_ATTACHMENT_STORE_OP_DONT_CARE, // storeOp
1536 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // stencilLoadOp
1537 VK_ATTACHMENT_STORE_OP_DONT_CARE, // stencilStoreOp
1538 VK_IMAGE_LAYOUT_UNDEFINED, // initialLayout
1539 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // finalLayout
1540 );
1541 const AttRef attachmentRef
1542 (
1543 // sType
1544 DE_NULL, // pNext
1545 (deUint32)attachments.size(), // attachment
1546 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // layout
1547 0u // aspectMask
1548 );
1549 colorAttachmentRefs.push_back(attachmentRef);
1550 attachments.push_back(multisampleAttachment);
1551 }
1552 {
1553 const AttDesc singlesampleAttachment
1554 (
1555 // sType
1556 DE_NULL, // pNext
1557 0u, // flags
1558 m_format, // format
1559 VK_SAMPLE_COUNT_1_BIT, // samples
1560 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // loadOp
1561 VK_ATTACHMENT_STORE_OP_STORE, // storeOp
1562 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // stencilLoadOp
1563 VK_ATTACHMENT_STORE_OP_DONT_CARE, // stencilStoreOp
1564 VK_IMAGE_LAYOUT_UNDEFINED, // initialLayout
1565 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL // finalLayout
1566 );
1567 const auto attachmentId = (usedResolveAttachment ? static_cast<deUint32>(attachments.size()) : VK_ATTACHMENT_UNUSED);
1568 const AttRef attachmentRef
1569 (
1570 // sType
1571 DE_NULL, // pNext
1572 attachmentId, // attachment
1573 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // layout
1574 0u // aspectMask
1575 );
1576 resolveAttachmentRefs.push_back(attachmentRef);
1577 attachments.push_back(singlesampleAttachment);
1578 }
1579 }
1580
1581 DE_ASSERT(colorAttachmentRefs.size() == resolveAttachmentRefs.size());
1582 DE_ASSERT(attachments.size() == colorAttachmentRefs.size() + resolveAttachmentRefs.size());
1583
1584 const SubpassDesc subpass
1585 (
1586 // sType
1587 DE_NULL, // pNext
1588 (VkSubpassDescriptionFlags)0, // flags
1589 VK_PIPELINE_BIND_POINT_GRAPHICS, // pipelineBindPoint
1590 0u, // viewMask
1591 0u, // inputAttachmentCount
1592 DE_NULL, // pInputAttachments
1593 (deUint32)colorAttachmentRefs.size(), // colorAttachmentCount
1594 &colorAttachmentRefs[0], // pColorAttachments
1595 &resolveAttachmentRefs[0], // pResolveAttachments
1596 DE_NULL, // pDepthStencilAttachment
1597 0u, // preserveAttachmentCount
1598 DE_NULL // pPreserveAttachments
1599 );
1600 const RenderPassCreateInfo renderPassCreator
1601 (
1602 // sType
1603 DE_NULL, // pNext
1604 (VkRenderPassCreateFlags)0u, // flags
1605 (deUint32)attachments.size(), // attachmentCount
1606 &attachments[0], // pAttachments
1607 1u, // subpassCount
1608 &subpass, // pSubpasses
1609 0u, // dependencyCount
1610 DE_NULL, // pDependencies
1611 0u, // correlatedViewMaskCount
1612 DE_NULL // pCorrelatedViewMasks
1613 );
1614
1615 return renderPassCreator.createRenderPass(vkd, device);
1616 }
1617
createRenderPassSwitch(bool usedResolveAttachment)1618 Move<VkRenderPass> MultisampleRenderPassTestInstance::createRenderPassSwitch (bool usedResolveAttachment)
1619 {
1620 switch (m_groupParams->renderingType)
1621 {
1622 case RENDERING_TYPE_RENDERPASS_LEGACY:
1623 return createRenderPass<RenderPass1Trait>(usedResolveAttachment);
1624 case RENDERING_TYPE_RENDERPASS2:
1625 return createRenderPass<RenderPass2Trait>(usedResolveAttachment);
1626 case RENDERING_TYPE_DYNAMIC_RENDERING:
1627 return Move<VkRenderPass>();
1628 default:
1629 TCU_THROW(InternalError, "Impossible");
1630 }
1631 }
1632
createRenderPassCompatible(void)1633 Move<VkRenderPass> MultisampleRenderPassTestInstance::createRenderPassCompatible (void)
1634 {
1635 if (m_testCompatibility)
1636 {
1637 // The compatible render pass is always created with a used resolve attachment.
1638 return createRenderPassSwitch(true);
1639 }
1640 else
1641 {
1642 return {};
1643 }
1644 }
1645
createRenderPipelineLayout(void)1646 Move<VkPipelineLayout> MultisampleRenderPassTestInstance::createRenderPipelineLayout (void)
1647 {
1648 const DeviceInterface& vkd = m_context.getDeviceInterface();
1649 VkDevice device = m_context.getDevice();
1650
1651 const VkPushConstantRange pushConstant =
1652 {
1653 VK_SHADER_STAGE_FRAGMENT_BIT,
1654 0u,
1655 4u
1656 };
1657 const VkPipelineLayoutCreateInfo createInfo =
1658 {
1659 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
1660 DE_NULL,
1661 (vk::VkPipelineLayoutCreateFlags)0,
1662
1663 0u,
1664 DE_NULL,
1665
1666 1u,
1667 &pushConstant
1668 };
1669
1670 return createPipelineLayout(vkd, device, &createInfo);
1671 }
1672
createRenderPipeline(void)1673 Move<VkPipeline> MultisampleRenderPassTestInstance::createRenderPipeline (void)
1674 {
1675 const DeviceInterface& vkd = m_context.getDeviceInterface();
1676 VkDevice device = m_context.getDevice();
1677 const vk::BinaryCollection& binaryCollection = m_context.getBinaryCollection();
1678 const Unique<VkShaderModule> vertexShaderModule (createShaderModule(vkd, device, binaryCollection.get("quad-vert"), 0u));
1679 const Unique<VkShaderModule> fragmentShaderModule (createShaderModule(vkd, device, binaryCollection.get("quad-frag"), 0u));
1680 const Move<VkShaderModule> geometryShaderModule (m_layerCount == 1 ? Move<VkShaderModule>() : createShaderModule(vkd, device, binaryCollection.get("geom"), 0u));
1681 // Disable blending
1682 const VkPipelineColorBlendAttachmentState attachmentBlendState =
1683 {
1684 VK_FALSE,
1685 VK_BLEND_FACTOR_SRC_ALPHA,
1686 VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
1687 VK_BLEND_OP_ADD,
1688 VK_BLEND_FACTOR_ONE,
1689 VK_BLEND_FACTOR_ONE,
1690 VK_BLEND_OP_ADD,
1691 VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT
1692 };
1693 std::vector<VkPipelineColorBlendAttachmentState> attachmentBlendStates(m_attachmentsCount, attachmentBlendState);
1694 const VkPipelineVertexInputStateCreateInfo vertexInputState =
1695 {
1696 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
1697 DE_NULL,
1698 (VkPipelineVertexInputStateCreateFlags)0u,
1699
1700 0u,
1701 DE_NULL,
1702
1703 0u,
1704 DE_NULL
1705 };
1706 const tcu::UVec2 renderArea (m_width, m_height);
1707 const std::vector<VkViewport> viewports (1, makeViewport(renderArea));
1708 const std::vector<VkRect2D> scissors (1, makeRect2D(renderArea));
1709
1710 const VkPipelineMultisampleStateCreateInfo multisampleState =
1711 {
1712 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
1713 DE_NULL,
1714 (VkPipelineMultisampleStateCreateFlags)0u,
1715
1716 sampleCountBitFromSampleCount(m_sampleCount),
1717 VK_FALSE,
1718 0.0f,
1719 DE_NULL,
1720 VK_FALSE,
1721 VK_FALSE,
1722 };
1723 const VkPipelineDepthStencilStateCreateInfo depthStencilState =
1724 {
1725 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
1726 DE_NULL,
1727 (VkPipelineDepthStencilStateCreateFlags)0u,
1728
1729 VK_FALSE,
1730 VK_TRUE,
1731 VK_COMPARE_OP_ALWAYS,
1732 VK_FALSE,
1733 VK_TRUE,
1734 {
1735 VK_STENCIL_OP_KEEP,
1736 VK_STENCIL_OP_INCREMENT_AND_WRAP,
1737 VK_STENCIL_OP_KEEP,
1738 VK_COMPARE_OP_ALWAYS,
1739 ~0u,
1740 ~0u,
1741 0xFFu / (m_sampleCount + 1)
1742 },
1743 {
1744 VK_STENCIL_OP_KEEP,
1745 VK_STENCIL_OP_INCREMENT_AND_WRAP,
1746 VK_STENCIL_OP_KEEP,
1747 VK_COMPARE_OP_ALWAYS,
1748 ~0u,
1749 ~0u,
1750 0xFFu / (m_sampleCount + 1)
1751 },
1752
1753 0.0f,
1754 1.0f
1755 };
1756 const VkPipelineColorBlendStateCreateInfo blendState =
1757 {
1758 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
1759 DE_NULL,
1760 (VkPipelineColorBlendStateCreateFlags)0u,
1761
1762 VK_FALSE,
1763 VK_LOGIC_OP_COPY,
1764 deUint32(attachmentBlendStates.size()),
1765 &attachmentBlendStates[0],
1766 { 0.0f, 0.0f, 0.0f, 0.0f }
1767 };
1768
1769 void* pNext = DE_NULL;
1770
1771 #ifndef CTS_USES_VULKANSC
1772 std::vector<VkFormat> attachmentFormats(m_attachmentsCount, m_format);
1773 VkPipelineRenderingCreateInfoKHR renderingCreateInfo
1774 {
1775 VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
1776 DE_NULL,
1777 0u,
1778 m_attachmentsCount,
1779 attachmentFormats.data(),
1780 VK_FORMAT_UNDEFINED,
1781 VK_FORMAT_UNDEFINED
1782 };
1783 if (m_groupParams->renderingType == RENDERING_TYPE_DYNAMIC_RENDERING)
1784 pNext = &renderingCreateInfo;
1785 #endif // CTS_USES_VULKANSC
1786
1787 return makeGraphicsPipeline(vkd, // const DeviceInterface& vk
1788 device, // const VkDevice device
1789 *m_renderPipelineLayout, // const VkPipelineLayout pipelineLayout
1790 *vertexShaderModule, // const VkShaderModule vertexShaderModule
1791 DE_NULL, // const VkShaderModule tessellationControlShaderModule
1792 DE_NULL, // const VkShaderModule tessellationEvalShaderModule
1793 m_layerCount != 1 ? *geometryShaderModule : DE_NULL,// const VkShaderModule geometryShaderModule
1794 *fragmentShaderModule, // const VkShaderModule fragmentShaderModule
1795 *m_renderPass, // const VkRenderPass renderPass
1796 viewports, // const std::vector<VkViewport>& viewports
1797 scissors, // const std::vector<VkRect2D>& scissors
1798 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // const VkPrimitiveTopology topology
1799 0u, // const deUint32 subpass
1800 0u, // const deUint32 patchControlPoints
1801 &vertexInputState, // const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo
1802 DE_NULL, // const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
1803 &multisampleState, // const VkPipelineMultisampleStateCreateInfo* multisampleStateCreateInfo
1804 &depthStencilState, // const VkPipelineDepthStencilStateCreateInfo* depthStencilStateCreateInfo
1805 &blendState, // const VkPipelineColorBlendStateCreateInfo* colorBlendStateCreateInfo
1806 DE_NULL, // const VkPipelineDynamicStateCreateInfo* dynamicStateCreateInfo
1807 pNext); // const void* pNext
1808 }
1809
1810 #ifndef CTS_USES_VULKANSC
beginSecondaryCmdBuffer(VkCommandBuffer cmdBuffer, VkRenderingFlagsKHR renderingFlags) const1811 void MultisampleRenderPassTestInstance::beginSecondaryCmdBuffer(VkCommandBuffer cmdBuffer, VkRenderingFlagsKHR renderingFlags) const
1812 {
1813 const DeviceInterface& vkd = m_context.getDeviceInterface();
1814 std::vector<VkFormat> formats(m_attachmentsCount, m_format);
1815
1816 VkCommandBufferInheritanceRenderingInfoKHR inheritanceRenderingInfo
1817 {
1818 VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR, // VkStructureType sType;
1819 DE_NULL, // const void* pNext;
1820 renderingFlags, // VkRenderingFlagsKHR flags;
1821 0u, // uint32_t viewMask;
1822 m_attachmentsCount, // uint32_t colorAttachmentCount;
1823 formats.data(), // const VkFormat* pColorAttachmentFormats;
1824 VK_FORMAT_UNDEFINED, // VkFormat depthAttachmentFormat;
1825 VK_FORMAT_UNDEFINED, // VkFormat stencilAttachmentFormat;
1826 m_sampleCount, // VkSampleCountFlagBits rasterizationSamples;
1827 };
1828
1829 const VkCommandBufferInheritanceInfo bufferInheritanceInfo = initVulkanStructure(&inheritanceRenderingInfo);
1830 VkCommandBufferUsageFlags usageFlags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
1831 if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
1832 usageFlags |= VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
1833
1834 const VkCommandBufferBeginInfo commandBufBeginParams
1835 {
1836 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
1837 DE_NULL, // const void* pNext;
1838 usageFlags, // VkCommandBufferUsageFlags flags;
1839 &bufferInheritanceInfo
1840 };
1841
1842 VK_CHECK(vkd.beginCommandBuffer(cmdBuffer, &commandBufBeginParams));
1843 }
1844 #endif // CTS_USES_VULKANSC
1845
1846 class MaxAttachmenstsRenderPassTestInstance : public MultisampleRenderPassTestBase
1847 {
1848 public:
1849 MaxAttachmenstsRenderPassTestInstance (Context& context, TestConfig config);
1850 ~MaxAttachmenstsRenderPassTestInstance (void);
1851
1852 tcu::TestStatus iterate (void);
1853
1854 private:
1855
1856 template<typename RenderpassSubpass>
1857 void submit (void);
1858 void submitSwitch (RenderingType renderingType);
1859 void verify (void);
1860
1861 Move<VkDescriptorSetLayout> createDescriptorSetLayout (void);
1862 Move<VkDescriptorPool> createDescriptorPool (void);
1863 Move<VkDescriptorSet> createDescriptorSet (void);
1864
1865 template<typename RenderPassTrait>
1866 Move<VkRenderPass> createRenderPass (void);
1867 Move<VkRenderPass> createRenderPassSwitch (const RenderingType renderingType);
1868 Move<VkPipelineLayout> createRenderPipelineLayout (bool secondSubpass);
1869 Move<VkPipeline> createRenderPipeline (bool secondSubpass);
1870
1871 private:
1872
1873 const std::vector<VkImageSp> m_multisampleImages;
1874 const std::vector<AllocationSp> m_multisampleImageMemory;
1875 const std::vector<VkImageViewSp> m_multisampleImageViews;
1876
1877 const std::vector<VkImageSp> m_singlesampleImages;
1878 const std::vector<AllocationSp> m_singlesampleImageMemory;
1879 const std::vector<VkImageViewSp> m_singlesampleImageViews;
1880
1881 const Unique<VkDescriptorSetLayout> m_descriptorSetLayout;
1882 const Unique<VkDescriptorPool> m_descriptorPool;
1883 const Unique<VkDescriptorSet> m_descriptorSet;
1884
1885 const Unique<VkRenderPass> m_renderPass;
1886 const Unique<VkFramebuffer> m_framebuffer;
1887
1888 const Unique<VkPipelineLayout> m_pipelineLayoutPass0;
1889 const Unique<VkPipeline> m_pipelinePass0;
1890 const Unique<VkPipelineLayout> m_pipelineLayoutPass1;
1891 const Unique<VkPipeline> m_pipelinePass1;
1892
1893 const std::vector<VkBufferSp> m_buffers;
1894 const std::vector<AllocationSp> m_bufferMemory;
1895
1896 const Unique<VkCommandPool> m_commandPool;
1897 tcu::ResultCollector m_resultCollector;
1898 };
1899
MaxAttachmenstsRenderPassTestInstance(Context& context, TestConfig config)1900 MaxAttachmenstsRenderPassTestInstance::MaxAttachmenstsRenderPassTestInstance (Context& context, TestConfig config)
1901 : MultisampleRenderPassTestBase(context, config)
1902
1903 , m_multisampleImages (createImages(m_sampleCount, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT))
1904 , m_multisampleImageMemory (createImageMemory(m_multisampleImages))
1905 , m_multisampleImageViews (createImageViews(m_multisampleImages))
1906
1907 , m_singlesampleImages (createImages(VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT))
1908 , m_singlesampleImageMemory (createImageMemory(m_singlesampleImages))
1909 , m_singlesampleImageViews (createImageViews(m_singlesampleImages))
1910
1911 , m_descriptorSetLayout (createDescriptorSetLayout())
1912 , m_descriptorPool (createDescriptorPool())
1913 , m_descriptorSet (createDescriptorSet())
1914
1915 , m_renderPass (createRenderPassSwitch(config.groupParams->renderingType))
1916 , m_framebuffer (createFramebuffer(m_multisampleImageViews, m_singlesampleImageViews, *m_renderPass))
1917
1918 , m_pipelineLayoutPass0 (createRenderPipelineLayout(0))
1919 , m_pipelinePass0 (createRenderPipeline(0))
1920 , m_pipelineLayoutPass1 (createRenderPipelineLayout(1))
1921 , m_pipelinePass1 (createRenderPipeline(1))
1922
1923 , m_buffers (createBuffers())
1924 , m_bufferMemory (createBufferMemory(m_buffers))
1925
1926 , m_commandPool (createCommandPool(context.getDeviceInterface(), context.getDevice(), VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, context.getUniversalQueueFamilyIndex()))
1927 {
1928 }
1929
~MaxAttachmenstsRenderPassTestInstance(void)1930 MaxAttachmenstsRenderPassTestInstance::~MaxAttachmenstsRenderPassTestInstance (void)
1931 {
1932 }
1933
1934 template<typename RenderpassSubpass>
submit(void)1935 void MaxAttachmenstsRenderPassTestInstance::submit (void)
1936 {
1937 const DeviceInterface& vkd (m_context.getDeviceInterface());
1938 const VkDevice device (m_context.getDevice());
1939 const Unique<VkCommandBuffer> commandBuffer (allocateCommandBuffer(vkd, device, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1940 const typename RenderpassSubpass::SubpassBeginInfo subpassBeginInfo (DE_NULL, VK_SUBPASS_CONTENTS_INLINE);
1941 const typename RenderpassSubpass::SubpassEndInfo subpassEndInfo (DE_NULL);
1942
1943 beginCommandBuffer(vkd, *commandBuffer);
1944
1945 // Memory barriers between previous copies and rendering
1946 {
1947 std::vector<VkImageMemoryBarrier> barriers;
1948
1949 for (size_t dstNdx = 0; dstNdx < m_singlesampleImages.size(); dstNdx++)
1950 {
1951 const VkImageMemoryBarrier barrier =
1952 {
1953 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
1954 DE_NULL,
1955
1956 VK_ACCESS_TRANSFER_READ_BIT,
1957 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
1958
1959 VK_IMAGE_LAYOUT_UNDEFINED,
1960 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
1961
1962 VK_QUEUE_FAMILY_IGNORED,
1963 VK_QUEUE_FAMILY_IGNORED,
1964
1965 **m_singlesampleImages[dstNdx],
1966 {
1967 VK_IMAGE_ASPECT_COLOR_BIT,
1968 0u,
1969 1u,
1970 0u,
1971 m_layerCount
1972 }
1973 };
1974
1975 barriers.push_back(barrier);
1976 }
1977
1978 vkd.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, (deUint32)barriers.size(), &barriers[0]);
1979 }
1980
1981 {
1982 const VkRenderPassBeginInfo beginInfo =
1983 {
1984 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
1985 DE_NULL,
1986
1987 *m_renderPass,
1988 *m_framebuffer,
1989
1990 {
1991 { 0u, 0u },
1992 { m_width, m_height }
1993 },
1994
1995 0u,
1996 DE_NULL
1997 };
1998 RenderpassSubpass::cmdBeginRenderPass(vkd, *commandBuffer, &beginInfo, &subpassBeginInfo);
1999 }
2000
2001 // Clear everything to black
2002 clearAttachments(*commandBuffer);
2003
2004 // First subpass - render black samples
2005 {
2006 vkd.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelinePass0);
2007 vkd.cmdDraw(*commandBuffer, 6u, 1u, 0u, 0u);
2008 }
2009
2010 // Second subpasss - merge attachments
2011 {
2012 RenderpassSubpass::cmdNextSubpass(vkd, *commandBuffer, &subpassBeginInfo, &subpassEndInfo);
2013 vkd.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelinePass1);
2014 vkd.cmdBindDescriptorSets(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayoutPass1, 0, 1u, &*m_descriptorSet, 0, NULL);
2015 vkd.cmdDraw(*commandBuffer, 6u, 1u, 0u, 0u);
2016 }
2017
2018 RenderpassSubpass::cmdEndRenderPass(vkd, *commandBuffer, &subpassEndInfo);
2019
2020 // Memory barriers between rendering and copies
2021 {
2022 std::vector<VkImageMemoryBarrier> barriers;
2023
2024 for (size_t dstNdx = 0; dstNdx < m_singlesampleImages.size(); dstNdx++)
2025 {
2026 const VkImageMemoryBarrier barrier =
2027 {
2028 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
2029 DE_NULL,
2030
2031 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
2032 VK_ACCESS_TRANSFER_READ_BIT,
2033
2034 VK_IMAGE_LAYOUT_GENERAL,
2035 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
2036
2037 VK_QUEUE_FAMILY_IGNORED,
2038 VK_QUEUE_FAMILY_IGNORED,
2039
2040 **m_singlesampleImages[dstNdx],
2041 {
2042 VK_IMAGE_ASPECT_COLOR_BIT,
2043 0u,
2044 1u,
2045 0u,
2046 m_layerCount
2047 }
2048 };
2049
2050 barriers.push_back(barrier);
2051 }
2052
2053 vkd.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, (deUint32)barriers.size(), &barriers[0]);
2054 }
2055
2056 // Copy image memory to buffers
2057 for (size_t dstNdx = 0; dstNdx < m_singlesampleImages.size(); dstNdx++)
2058 {
2059 const VkBufferImageCopy region =
2060 {
2061 0u,
2062 0u,
2063 0u,
2064 {
2065 VK_IMAGE_ASPECT_COLOR_BIT,
2066 0u,
2067 0u,
2068 m_layerCount,
2069 },
2070 { 0u, 0u, 0u },
2071 { m_width, m_height, 1u }
2072 };
2073
2074 vkd.cmdCopyImageToBuffer(*commandBuffer, **m_singlesampleImages[dstNdx], VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **m_buffers[dstNdx], 1u, ®ion);
2075 }
2076
2077 // Memory barriers between copies and host access
2078 {
2079 std::vector<VkBufferMemoryBarrier> barriers;
2080
2081 for (size_t dstNdx = 0; dstNdx < m_buffers.size(); dstNdx++)
2082 {
2083 const VkBufferMemoryBarrier barrier =
2084 {
2085 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
2086 DE_NULL,
2087
2088 VK_ACCESS_TRANSFER_WRITE_BIT,
2089 VK_ACCESS_HOST_READ_BIT,
2090
2091 VK_QUEUE_FAMILY_IGNORED,
2092 VK_QUEUE_FAMILY_IGNORED,
2093
2094 **m_buffers[dstNdx],
2095 0u,
2096 VK_WHOLE_SIZE
2097 };
2098
2099 barriers.push_back(barrier);
2100 }
2101
2102 vkd.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, (deUint32)barriers.size(), &barriers[0], 0u, DE_NULL);
2103 }
2104
2105 endCommandBuffer(vkd, *commandBuffer);
2106
2107 submitCommandsAndWait(vkd, device, m_context.getUniversalQueue(), *commandBuffer);
2108
2109 for (size_t memoryBufferNdx = 0; memoryBufferNdx < m_bufferMemory.size(); memoryBufferNdx++)
2110 invalidateMappedMemoryRange(vkd, device, m_bufferMemory[memoryBufferNdx]->getMemory(), 0u, VK_WHOLE_SIZE);
2111 }
2112
submitSwitch(RenderingType renderingType)2113 void MaxAttachmenstsRenderPassTestInstance::submitSwitch (RenderingType renderingType)
2114 {
2115 switch (renderingType)
2116 {
2117 case RENDERING_TYPE_RENDERPASS_LEGACY:
2118 submit<RenderpassSubpass1>();
2119 break;
2120 case RENDERING_TYPE_RENDERPASS2:
2121 submit<RenderpassSubpass2>();
2122 break;
2123 default:
2124 TCU_THROW(InternalError, "Impossible");
2125 }
2126 }
2127
2128 template <typename VecType>
isValueAboveThreshold1(const VecType& vale, const VecType& threshold)2129 bool isValueAboveThreshold1 (const VecType& vale, const VecType& threshold)
2130 {
2131 return (vale[0] > threshold[0]);
2132 }
2133
2134 template <typename VecType>
isValueAboveThreshold2(const VecType& vale, const VecType& threshold)2135 bool isValueAboveThreshold2 (const VecType& vale, const VecType& threshold)
2136 {
2137 return (vale[0] > threshold[0]) || (vale[1] > threshold[1]);
2138 }
2139
2140 template <typename VecType>
isValueAboveThreshold3(const VecType& vale, const VecType& threshold)2141 bool isValueAboveThreshold3 (const VecType& vale, const VecType& threshold)
2142 {
2143 return (vale[0] > threshold[0]) || (vale[1] > threshold[1]) || (vale[2] > threshold[2]);
2144 }
2145
2146 template <typename VecType>
isValueAboveThreshold4(const VecType& vale, const VecType& threshold)2147 bool isValueAboveThreshold4 (const VecType& vale, const VecType& threshold)
2148 {
2149 return (vale[0] > threshold[0]) || (vale[1] > threshold[1]) || (vale[2] > threshold[2]) || (vale[3] > threshold[3]);
2150 }
2151
verify(void)2152 void MaxAttachmenstsRenderPassTestInstance::verify (void)
2153 {
2154 const Vec4 errorColor (1.0f, 0.0f, 0.0f, 1.0f);
2155 const Vec4 okColor (0.0f, 1.0f, 0.0f, 1.0f);
2156 const tcu::TextureFormat format (mapVkFormat(m_format));
2157 const tcu::TextureChannelClass channelClass (tcu::getTextureChannelClass(format.type));
2158 const int componentCount (tcu::getNumUsedChannels(format.order));
2159 const int outputsCount = m_attachmentsCount / 2;
2160
2161 DE_ASSERT((componentCount >= 0) && (componentCount < 5));
2162
2163 std::vector<tcu::ConstPixelBufferAccess> accesses;
2164 for (int outputNdx = 0; outputNdx < outputsCount; ++outputNdx)
2165 {
2166 void* const ptr = m_bufferMemory[outputNdx]->getHostPtr();
2167 accesses.push_back(tcu::ConstPixelBufferAccess(format, m_width, m_height, 1, ptr));
2168 }
2169
2170 tcu::TextureLevel errorMask (tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), m_width, m_height, outputsCount);
2171 tcu::TestLog& log (m_context.getTestContext().getLog());
2172 bool isOk = true;
2173
2174 switch (channelClass)
2175 {
2176 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
2177 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
2178 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
2179 {
2180 const Vec4 refColor(0.0f, 0.3f, 0.6f, 0.75f);
2181 const Vec4 threshold(getFormatThreshold());
2182
2183 typedef bool(*ValueAboveThresholdFn)(const Vec4&, const Vec4&);
2184 ValueAboveThresholdFn componentToFnMap[4] =
2185 {
2186 isValueAboveThreshold1<Vec4>,
2187 isValueAboveThreshold2<Vec4>,
2188 isValueAboveThreshold3<Vec4>,
2189 isValueAboveThreshold4<Vec4>
2190 };
2191 ValueAboveThresholdFn isValueAboveThreshold = componentToFnMap[componentCount - 1];
2192 bool isSRGBFormat = tcu::isSRGB(format);
2193
2194 for (int outputNdx = 0; outputNdx < outputsCount; outputNdx++)
2195 for (int y = 0; y < (int)m_height; y++)
2196 for (int x = 0; x < (int)m_width; x++)
2197 {
2198 Vec4 color = accesses[outputNdx].getPixel(x, y);
2199 if (isSRGBFormat)
2200 color = tcu::sRGBToLinear(color);
2201
2202 const Vec4 diff(tcu::abs(color - refColor));
2203
2204 if (isValueAboveThreshold(diff, threshold))
2205 {
2206 isOk = false;
2207 errorMask.getAccess().setPixel(errorColor, x, y, outputNdx);
2208 break;
2209 }
2210 else
2211 errorMask.getAccess().setPixel(okColor, x, y, outputNdx);
2212 }
2213 break;
2214 }
2215
2216 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
2217 {
2218 const UVec4 refColor(0, 48, 144, 189);
2219 UVec4 threshold(1, 1, 1, 1);
2220
2221 if (m_format == VK_FORMAT_A2B10G10R10_UINT_PACK32)
2222 threshold[3] = 200;
2223
2224 typedef bool(*ValueAboveThresholdFn)(const UVec4&, const UVec4&);
2225 ValueAboveThresholdFn componentToFnMap[4] =
2226 {
2227 isValueAboveThreshold1<UVec4>,
2228 isValueAboveThreshold2<UVec4>,
2229 isValueAboveThreshold3<UVec4>,
2230 isValueAboveThreshold4<UVec4>
2231 };
2232 ValueAboveThresholdFn isValueAboveThreshold = componentToFnMap[componentCount - 1];
2233
2234 for (int outputNdx = 0; outputNdx < outputsCount; outputNdx++)
2235 for (int y = 0; y < (int)m_height; y++)
2236 for (int x = 0; x < (int)m_width; x++)
2237 {
2238 const UVec4 color (accesses[outputNdx].getPixelUint(x, y));
2239 const UVec4 diff (std::abs(int(color.x()) - int(refColor.x())),
2240 std::abs(int(color.y()) - int(refColor.y())),
2241 std::abs(int(color.z()) - int(refColor.z())),
2242 std::abs(int(color.w()) - int(refColor.w())));
2243
2244 if (isValueAboveThreshold(diff, threshold))
2245 {
2246 isOk = false;
2247 errorMask.getAccess().setPixel(errorColor, x, y, outputNdx);
2248 break;
2249 }
2250 else
2251 errorMask.getAccess().setPixel(okColor, x, y, outputNdx);
2252 }
2253 break;
2254 }
2255
2256 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
2257 {
2258 const IVec4 refColor (0, 24, 75, 93);
2259 const IVec4 threshold (1, 1, 1, 1);
2260
2261 typedef bool(*ValueAboveThresholdFn)(const IVec4&, const IVec4&);
2262 ValueAboveThresholdFn componentToFnMap[4] =
2263 {
2264 isValueAboveThreshold1<IVec4>,
2265 isValueAboveThreshold2<IVec4>,
2266 isValueAboveThreshold3<IVec4>,
2267 isValueAboveThreshold4<IVec4>
2268 };
2269 ValueAboveThresholdFn isValueAboveThreshold = componentToFnMap[componentCount - 1];
2270
2271 for (int outputNdx = 0; outputNdx < outputsCount; outputNdx++)
2272 for (int y = 0; y < (int)m_height; y++)
2273 for (int x = 0; x < (int)m_width; x++)
2274 {
2275 const IVec4 color (accesses[outputNdx].getPixelInt(x, y));
2276 const IVec4 diff (std::abs(color.x() - refColor.x()),
2277 std::abs(color.y() - refColor.y()),
2278 std::abs(color.z() - refColor.z()),
2279 std::abs(color.w() - refColor.w()));
2280
2281 if (isValueAboveThreshold(diff, threshold))
2282 {
2283 isOk = false;
2284 errorMask.getAccess().setPixel(errorColor, x, y, outputNdx);
2285 break;
2286 }
2287 else
2288 errorMask.getAccess().setPixel(okColor, x, y, outputNdx);
2289 }
2290 break;
2291 }
2292
2293 default:
2294 DE_FATAL("Unknown channel class");
2295 }
2296
2297 if (!isOk)
2298 {
2299 const std::string sectionName ("MaxAttachmentsVerify");
2300 const tcu::ScopedLogSection section (log, sectionName, sectionName);
2301
2302 logImage("ErrorMask", errorMask.getAccess());
2303 m_resultCollector.fail("Fail");
2304 }
2305 }
2306
iterate(void)2307 tcu::TestStatus MaxAttachmenstsRenderPassTestInstance::iterate(void)
2308 {
2309 submitSwitch(m_groupParams->renderingType);
2310 verify();
2311
2312 return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage());
2313 }
2314
createDescriptorSetLayout()2315 Move<VkDescriptorSetLayout> MaxAttachmenstsRenderPassTestInstance::createDescriptorSetLayout()
2316 {
2317 const VkDescriptorSetLayoutBinding bindingTemplate =
2318 {
2319 0, // binding
2320 VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, // descriptorType
2321 1u, // descriptorCount
2322 VK_SHADER_STAGE_FRAGMENT_BIT, // stageFlags
2323 DE_NULL // pImmutableSamplers
2324 };
2325
2326 std::vector<VkDescriptorSetLayoutBinding> bindings(m_attachmentsCount, bindingTemplate);
2327 for (deUint32 idx = 0; idx < m_attachmentsCount; ++idx)
2328 bindings[idx].binding = idx;
2329
2330 const VkDescriptorSetLayoutCreateInfo createInfo =
2331 {
2332 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // sType
2333 DE_NULL, // pNext
2334 0u, // flags
2335 m_attachmentsCount, // bindingCount
2336 &bindings[0] // pBindings
2337 };
2338
2339 return ::createDescriptorSetLayout(m_context.getDeviceInterface(), m_context.getDevice(), &createInfo);
2340 }
2341
createDescriptorPool()2342 Move<VkDescriptorPool> MaxAttachmenstsRenderPassTestInstance::createDescriptorPool()
2343 {
2344 const VkDescriptorPoolSize size =
2345 {
2346 VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, // type
2347 m_attachmentsCount // descriptorCount
2348 };
2349
2350 const VkDescriptorPoolCreateInfo createInfo =
2351 {
2352 VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, // sType
2353 DE_NULL, // pNext
2354 VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, // flags
2355 1u, // maxSets
2356 1u, // poolSizeCount
2357 &size // pPoolSizes
2358 };
2359
2360 return ::createDescriptorPool(m_context.getDeviceInterface(), m_context.getDevice(), &createInfo);
2361 }
2362
createDescriptorSet()2363 Move<VkDescriptorSet> MaxAttachmenstsRenderPassTestInstance::createDescriptorSet()
2364 {
2365 const VkDescriptorSetAllocateInfo allocateInfo =
2366 {
2367 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // sType
2368 DE_NULL, // pNext
2369 *m_descriptorPool, // descriptorPool
2370 1u, // descriptorSetCount
2371 &*m_descriptorSetLayout // pSetLayouts
2372 };
2373
2374 const vk::DeviceInterface& vkd = m_context.getDeviceInterface();
2375 vk::VkDevice device = m_context.getDevice();
2376 Move<VkDescriptorSet> descriptorSet = allocateDescriptorSet(vkd, device, &allocateInfo);
2377 vector<VkDescriptorImageInfo> descriptorImageInfo (m_attachmentsCount);
2378 vector<VkWriteDescriptorSet> descriptorWrites (m_attachmentsCount);
2379
2380 for (deUint32 idx = 0; idx < m_attachmentsCount; ++idx)
2381 {
2382 const VkDescriptorImageInfo imageInfo =
2383 {
2384 DE_NULL, // VkSampler sampler
2385 **m_singlesampleImageViews[idx], // VkImageView imageView
2386 VK_IMAGE_LAYOUT_GENERAL // VkImageLayout imageLayout
2387 };
2388 descriptorImageInfo[idx] = imageInfo;
2389
2390 const VkWriteDescriptorSet write =
2391 {
2392 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // VkStructureType sType
2393 DE_NULL, // const void* pNext
2394 *descriptorSet, // VkDescriptorSet dstSet
2395 (deUint32)idx, // uint32_t dstBinding
2396 0u, // uint32_t dstArrayElement
2397 1u, // uint32_t descriptorCount
2398 VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, // VkDescriptorType descriptorType
2399 &descriptorImageInfo[idx], // const VkDescriptorImageInfo* pImageInfo
2400 DE_NULL, // const VkDescriptorBufferInfo* pBufferInfo
2401 DE_NULL // const VkBufferView* pTexelBufferView
2402 };
2403
2404 descriptorWrites[idx] = write;
2405 }
2406
2407 vkd.updateDescriptorSets(device, (deUint32)descriptorWrites.size(), &descriptorWrites[0], 0u, DE_NULL);
2408 return descriptorSet;
2409 }
2410
2411 template<typename RenderPassTrait>
createRenderPass(void)2412 Move<VkRenderPass> MaxAttachmenstsRenderPassTestInstance::createRenderPass(void)
2413 {
2414 // make name for RenderPass1Trait or RenderPass2Trait shorter
2415 typedef RenderPassTrait RPT;
2416
2417 typedef typename RPT::AttDesc AttDesc;
2418 typedef typename RPT::AttRef AttRef;
2419 typedef typename RPT::SubpassDep SubpassDep;
2420 typedef typename RPT::SubpassDesc SubpassDesc;
2421 typedef typename RPT::RenderPassCreateInfo RenderPassCreateInfo;
2422
2423 const DeviceInterface& vkd = m_context.getDeviceInterface();
2424 VkDevice device = m_context.getDevice();
2425 std::vector<AttDesc> attachments;
2426 std::vector<AttRef> sp0colorAttachmentRefs;
2427 std::vector<AttRef> sp0resolveAttachmentRefs;
2428 std::vector<AttRef> sp1inAttachmentRefs;
2429 std::vector<AttRef> sp1colorAttachmentRefs;
2430
2431 for (size_t attachmentNdx = 0; attachmentNdx < m_attachmentsCount; attachmentNdx++)
2432 {
2433 // define first subpass outputs
2434 {
2435 const AttDesc multisampleAttachment
2436 (
2437 DE_NULL, // pNext
2438 0u, // flags
2439 m_format, // format
2440 m_sampleCount, // samples
2441 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // loadOp
2442 VK_ATTACHMENT_STORE_OP_STORE, // storeOp
2443 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // stencilLoadOp
2444 VK_ATTACHMENT_STORE_OP_DONT_CARE, // stencilStoreOp
2445 VK_IMAGE_LAYOUT_UNDEFINED, // initialLayout
2446 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // finalLayout
2447 );
2448 const AttRef attachmentRef
2449 (
2450 DE_NULL,
2451 (deUint32)attachments.size(), // attachment
2452 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // layout
2453 0u // aspectMask
2454 );
2455 sp0colorAttachmentRefs.push_back(attachmentRef);
2456 attachments.push_back(multisampleAttachment);
2457 }
2458 // define first subpass resolve attachments
2459 {
2460 const AttDesc singlesampleAttachment
2461 (
2462 DE_NULL, // pNext
2463 0u, // flags
2464 m_format, // format
2465 VK_SAMPLE_COUNT_1_BIT, // samples
2466 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // loadOp
2467 VK_ATTACHMENT_STORE_OP_STORE, // storeOp
2468 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // stencilLoadOp
2469 VK_ATTACHMENT_STORE_OP_DONT_CARE, // stencilStoreOp
2470 VK_IMAGE_LAYOUT_UNDEFINED, // initialLayout
2471 VK_IMAGE_LAYOUT_GENERAL // finalLayout
2472 );
2473 const AttRef attachmentRef
2474 (
2475 DE_NULL, // pNext
2476 (deUint32)attachments.size(), // attachment
2477 VK_IMAGE_LAYOUT_GENERAL, // layout
2478 0u // aspectMask
2479 );
2480 sp0resolveAttachmentRefs.push_back(attachmentRef);
2481 attachments.push_back(singlesampleAttachment);
2482 }
2483 // define second subpass inputs
2484 {
2485 const AttRef attachmentRef
2486 (
2487 DE_NULL, // pNext
2488 (deUint32)attachments.size() - 1, // attachment
2489 VK_IMAGE_LAYOUT_GENERAL, // layout
2490 VK_IMAGE_ASPECT_COLOR_BIT // aspectMask
2491 );
2492 sp1inAttachmentRefs.push_back(attachmentRef);
2493 }
2494 // define second subpass outputs - it merges pairs of
2495 // results that were produced by the first subpass
2496 if (attachmentNdx < (m_attachmentsCount / 2))
2497 {
2498 const AttRef colorAttachmentRef
2499 (
2500 DE_NULL, // pNext
2501 (deUint32)attachments.size() - 1, // attachment
2502 VK_IMAGE_LAYOUT_GENERAL, // layout
2503 0u // aspectMask
2504 );
2505 sp1colorAttachmentRefs.push_back(colorAttachmentRef);
2506 }
2507 }
2508
2509 DE_ASSERT(sp0colorAttachmentRefs.size() == sp0resolveAttachmentRefs.size());
2510 DE_ASSERT(attachments.size() == sp0colorAttachmentRefs.size() + sp0resolveAttachmentRefs.size());
2511
2512 {
2513 const SubpassDesc subpass0
2514 (
2515 // sType
2516 DE_NULL, // pNext
2517 (VkSubpassDescriptionFlags)0, // flags
2518 VK_PIPELINE_BIND_POINT_GRAPHICS, // pipelineBindPoint
2519 0u, // viewMask
2520 0u, // inputAttachmentCount
2521 DE_NULL, // pInputAttachments
2522 (deUint32)sp0colorAttachmentRefs.size(), // colorAttachmentCount
2523 &sp0colorAttachmentRefs[0], // pColorAttachments
2524 &sp0resolveAttachmentRefs[0], // pResolveAttachments
2525 DE_NULL, // pDepthStencilAttachment
2526 0u, // preserveAttachmentCount
2527 DE_NULL // pPreserveAttachments
2528 );
2529 const SubpassDesc subpass1
2530 (
2531 // sType
2532 DE_NULL, // pNext
2533 (VkSubpassDescriptionFlags)0, // flags
2534 VK_PIPELINE_BIND_POINT_GRAPHICS, // pipelineBindPoint
2535 0u, // viewMask
2536 (deUint32)sp1inAttachmentRefs.size(), // inputAttachmentCount
2537 &sp1inAttachmentRefs[0], // pInputAttachments
2538 (deUint32)sp1colorAttachmentRefs.size(), // colorAttachmentCount
2539 &sp1colorAttachmentRefs[0], // pColorAttachments
2540 DE_NULL, // pResolveAttachments
2541 DE_NULL, // pDepthStencilAttachment
2542 0u, // preserveAttachmentCount
2543 DE_NULL // pPreserveAttachments
2544 );
2545 SubpassDesc subpasses[] =
2546 {
2547 subpass0,
2548 subpass1
2549 };
2550 const SubpassDep subpassDependency
2551 (
2552 DE_NULL, // pNext
2553 0u, // srcSubpass
2554 1u, // dstSubpass
2555 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, // srcStageMask
2556 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, // dstStageMask
2557 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // srcAccessMask
2558 VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, // dstAccessMask
2559 0u, // dependencyFlags
2560 0u // viewOffset
2561 );
2562 const RenderPassCreateInfo renderPassCreator
2563 (
2564 // sType
2565 DE_NULL, // pNext
2566 (VkRenderPassCreateFlags)0u, // flags
2567 (deUint32)attachments.size(), // attachmentCount
2568 &attachments[0], // pAttachments
2569 2u, // subpassCount
2570 subpasses, // pSubpasses
2571 1u, // dependencyCount
2572 &subpassDependency, // pDependencies
2573 0u, // correlatedViewMaskCount
2574 DE_NULL // pCorrelatedViewMasks
2575 );
2576
2577 return renderPassCreator.createRenderPass(vkd, device);
2578 }
2579 }
2580
createRenderPassSwitch(const RenderingType renderingType)2581 Move<VkRenderPass> MaxAttachmenstsRenderPassTestInstance::createRenderPassSwitch(const RenderingType renderingType)
2582 {
2583 switch (renderingType)
2584 {
2585 case RENDERING_TYPE_RENDERPASS_LEGACY:
2586 return createRenderPass<RenderPass1Trait>();
2587 case RENDERING_TYPE_RENDERPASS2:
2588 return createRenderPass<RenderPass2Trait>();
2589 default:
2590 TCU_THROW(InternalError, "Impossible");
2591 }
2592 }
2593
createRenderPipelineLayout(bool secondSubpass)2594 Move<VkPipelineLayout> MaxAttachmenstsRenderPassTestInstance::createRenderPipelineLayout(bool secondSubpass)
2595 {
2596 const DeviceInterface& vkd = m_context.getDeviceInterface();
2597 VkDevice device = m_context.getDevice();
2598
2599 const VkPipelineLayoutCreateInfo createInfo =
2600 {
2601 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
2602 DE_NULL,
2603 (vk::VkPipelineLayoutCreateFlags)0,
2604
2605 secondSubpass ? 1u : 0u,
2606 secondSubpass ? &*m_descriptorSetLayout : DE_NULL,
2607
2608 0u,
2609 DE_NULL
2610 };
2611
2612 return createPipelineLayout(vkd, device, &createInfo);
2613 }
2614
createRenderPipeline(bool secondSubpass)2615 Move<VkPipeline> MaxAttachmenstsRenderPassTestInstance::createRenderPipeline(bool secondSubpass)
2616 {
2617 const DeviceInterface& vkd = m_context.getDeviceInterface();
2618 VkDevice device = m_context.getDevice();
2619 const vk::BinaryCollection& binaryCollection = m_context.getBinaryCollection();
2620 VkSampleCountFlagBits sampleCount = sampleCountBitFromSampleCount(m_sampleCount);
2621 deUint32 blendStatesCount = m_attachmentsCount;
2622 std::string fragShaderNameBase = "quad-frag-sp0-";
2623
2624 if (secondSubpass)
2625 {
2626 sampleCount = VK_SAMPLE_COUNT_1_BIT;
2627 blendStatesCount /= 2;
2628 fragShaderNameBase = "quad-frag-sp1-";
2629 }
2630
2631 std::string fragShaderName = fragShaderNameBase + de::toString(m_attachmentsCount);
2632 const Unique<VkShaderModule> vertexShaderModule (createShaderModule(vkd, device, binaryCollection.get("quad-vert"), 0u));
2633 const Unique<VkShaderModule> fragmentShaderModule (createShaderModule(vkd, device, binaryCollection.get(fragShaderName), 0u));
2634 const Move<VkShaderModule> geometryShaderModule (m_layerCount == 1 ? Move<VkShaderModule>() : createShaderModule(vkd, device, binaryCollection.get("geom"), 0u));
2635
2636 // Disable blending
2637 const VkPipelineColorBlendAttachmentState attachmentBlendState =
2638 {
2639 VK_FALSE,
2640 VK_BLEND_FACTOR_SRC_ALPHA,
2641 VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
2642 VK_BLEND_OP_ADD,
2643 VK_BLEND_FACTOR_ONE,
2644 VK_BLEND_FACTOR_ONE,
2645 VK_BLEND_OP_ADD,
2646 VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT
2647 };
2648 std::vector<VkPipelineColorBlendAttachmentState> attachmentBlendStates(blendStatesCount, attachmentBlendState);
2649 const VkPipelineVertexInputStateCreateInfo vertexInputState =
2650 {
2651 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
2652 DE_NULL,
2653 (VkPipelineVertexInputStateCreateFlags)0u,
2654
2655 0u,
2656 DE_NULL,
2657
2658 0u,
2659 DE_NULL
2660 };
2661 const tcu::UVec2 renderArea (m_width, m_height);
2662 const std::vector<VkViewport> viewports (1, makeViewport(renderArea));
2663 const std::vector<VkRect2D> scissors (1, makeRect2D(renderArea));
2664
2665 const VkPipelineMultisampleStateCreateInfo multisampleState =
2666 {
2667 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
2668 DE_NULL,
2669 (VkPipelineMultisampleStateCreateFlags)0u,
2670
2671 sampleCount,
2672 VK_FALSE,
2673 0.0f,
2674 DE_NULL,
2675 VK_FALSE,
2676 VK_FALSE,
2677 };
2678 const VkPipelineDepthStencilStateCreateInfo depthStencilState =
2679 {
2680 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
2681 DE_NULL,
2682 (VkPipelineDepthStencilStateCreateFlags)0u,
2683
2684 VK_FALSE,
2685 VK_TRUE,
2686 VK_COMPARE_OP_ALWAYS,
2687 VK_FALSE,
2688 VK_TRUE,
2689 {
2690 VK_STENCIL_OP_KEEP,
2691 VK_STENCIL_OP_INCREMENT_AND_WRAP,
2692 VK_STENCIL_OP_KEEP,
2693 VK_COMPARE_OP_ALWAYS,
2694 ~0u,
2695 ~0u,
2696 0xFFu / (m_sampleCount + 1)
2697 },
2698 {
2699 VK_STENCIL_OP_KEEP,
2700 VK_STENCIL_OP_INCREMENT_AND_WRAP,
2701 VK_STENCIL_OP_KEEP,
2702 VK_COMPARE_OP_ALWAYS,
2703 ~0u,
2704 ~0u,
2705 0xFFu / (m_sampleCount + 1)
2706 },
2707
2708 0.0f,
2709 1.0f
2710 };
2711 const VkPipelineColorBlendStateCreateInfo blendState =
2712 {
2713 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
2714 DE_NULL,
2715 (VkPipelineColorBlendStateCreateFlags)0u,
2716
2717 VK_FALSE,
2718 VK_LOGIC_OP_COPY,
2719 deUint32(attachmentBlendStates.size()),
2720 &attachmentBlendStates[0],
2721 { 0.0f, 0.0f, 0.0f, 0.0f }
2722 };
2723
2724 return makeGraphicsPipeline(vkd, // vk
2725 device, // device
2726 secondSubpass ? *m_pipelineLayoutPass1 : *m_pipelineLayoutPass0, // pipelineLayout
2727 *vertexShaderModule, // vertexShaderModule
2728 DE_NULL, // tessellationControlShaderModule
2729 DE_NULL, // tessellationEvalShaderModule
2730 m_layerCount != 1 ? *geometryShaderModule : DE_NULL, // geometryShaderModule
2731 *fragmentShaderModule, // fragmentShaderModule
2732 *m_renderPass, // renderPass
2733 viewports, // viewports
2734 scissors, // scissors
2735 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // topology
2736 secondSubpass, // subpass
2737 0u, // patchControlPoints
2738 &vertexInputState, // vertexInputStateCreateInfo
2739 DE_NULL, // rasterizationStateCreateInfo
2740 &multisampleState, // multisampleStateCreateInfo
2741 &depthStencilState, // depthStencilStateCreateInfo
2742 &blendState); // colorBlendStateCreateInfo
2743 }
2744
2745 class MultisampleRenderPassResolveLevelTestInstance : public MultisampleRenderPassTestInstance
2746 {
2747 public:
2748 MultisampleRenderPassResolveLevelTestInstance (Context& context, TestConfig2 config);
2749 ~MultisampleRenderPassResolveLevelTestInstance (void) = default;
2750 };
2751
MultisampleRenderPassResolveLevelTestInstance(Context& context, TestConfig2 config)2752 MultisampleRenderPassResolveLevelTestInstance::MultisampleRenderPassResolveLevelTestInstance (Context& context, TestConfig2 config)
2753 : MultisampleRenderPassTestInstance(context, config, config.resolveLevel)
2754 {
2755 }
2756
2757 struct Programs
2758 {
initvkt::__anon29771::Programs2759 void init(vk::SourceCollections& dst, TestConfig config) const
2760 {
2761 const tcu::TextureFormat format (mapVkFormat(config.format));
2762 const tcu::TextureChannelClass channelClass (tcu::getTextureChannelClass(format.type));
2763
2764 dst.glslSources.add("quad-vert") << glu::VertexSource(
2765 "#version 450\n"
2766 "out gl_PerVertex {\n"
2767 "\tvec4 gl_Position;\n"
2768 "};\n"
2769 "highp float;\n"
2770 "void main (void) {\n"
2771 "\tgl_Position = vec4(((gl_VertexIndex + 2) / 3) % 2 == 0 ? -1.0 : 1.0,\n"
2772 "\t ((gl_VertexIndex + 1) / 3) % 2 == 0 ? -1.0 : 1.0, 0.0, 1.0);\n"
2773 "}\n");
2774
2775 if (config.layerCount > 1)
2776 {
2777 std::ostringstream src;
2778
2779 src << "#version 450\n"
2780 << "highp float;\n"
2781 << "\n"
2782 << "layout(triangles) in;\n"
2783 << "layout(triangle_strip, max_vertices = " << 3 * 2 * config.layerCount << ") out;\n"
2784 << "\n"
2785 << "in gl_PerVertex {\n"
2786 << " vec4 gl_Position;\n"
2787 << "} gl_in[];\n"
2788 << "\n"
2789 << "out gl_PerVertex {\n"
2790 << " vec4 gl_Position;\n"
2791 << "};\n"
2792 << "\n"
2793 << "void main (void) {\n"
2794 << " for (int layerNdx = 0; layerNdx < " << config.layerCount << "; ++layerNdx) {\n"
2795 << " for(int vertexNdx = 0; vertexNdx < gl_in.length(); vertexNdx++) {\n"
2796 << " gl_Position = gl_in[vertexNdx].gl_Position;\n"
2797 << " gl_Layer = layerNdx;\n"
2798 << " EmitVertex();\n"
2799 << " };\n"
2800 << " EndPrimitive();\n"
2801 << " };\n"
2802 << "}\n";
2803
2804 dst.glslSources.add("geom") << glu::GeometrySource(src.str());
2805 }
2806
2807 const tcu::StringTemplate genericLayoutTemplate("layout(location = ${INDEX}) out ${TYPE_PREFIX}vec4 o_color${INDEX};\n");
2808 const tcu::StringTemplate genericBodyTemplate("\to_color${INDEX} = ${TYPE_PREFIX}vec4(${COLOR_VAL});\n");
2809
2810 if (config.testType == RESOLVE || config.testType == COMPATIBILITY)
2811 {
2812 const tcu::StringTemplate fragTemplate("#version 450\n"
2813 "layout(push_constant) uniform PushConstant {\n"
2814 "\thighp uint sampleMask;\n"
2815 "} pushConstants;\n"
2816 "${LAYOUT}"
2817 "void main (void)\n"
2818 "{\n"
2819 "${BODY}"
2820 "}\n");
2821
2822 std::map<std::string, std::string> parameters;
2823 switch (channelClass)
2824 {
2825 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
2826 parameters["TYPE_PREFIX"] = "u";
2827 parameters["COLOR_VAL"] = "255";
2828 break;
2829
2830 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
2831 parameters["TYPE_PREFIX"] = "i";
2832 parameters["COLOR_VAL"] = "127";
2833 break;
2834
2835 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
2836 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
2837 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
2838 parameters["TYPE_PREFIX"] = "";
2839 parameters["COLOR_VAL"] = "1.0";
2840 break;
2841
2842 default:
2843 DE_FATAL("Unknown channel class");
2844 }
2845
2846 std::string layoutDefinitions = "";
2847 std::string shaderBody = "\tgl_SampleMask[0] = int(pushConstants.sampleMask);\n";
2848
2849 for (deUint32 attIdx = 0; attIdx < config.attachmentCount; ++attIdx)
2850 {
2851 parameters["INDEX"] = de::toString(attIdx);
2852 layoutDefinitions += genericLayoutTemplate.specialize(parameters);
2853 shaderBody += genericBodyTemplate.specialize(parameters);
2854 }
2855
2856 parameters["LAYOUT"] = layoutDefinitions;
2857 parameters["BODY"] = shaderBody;
2858 dst.glslSources.add("quad-frag") << glu::FragmentSource(fragTemplate.specialize(parameters));
2859 }
2860 else // MAX_ATTACMENTS
2861 {
2862 const tcu::StringTemplate fragTemplate("#version 450\n"
2863 "${LAYOUT}"
2864 "void main (void)\n"
2865 "{\n"
2866 "${BODY}"
2867 "}\n");
2868
2869 std::map<std::string, std::string> parameters;
2870 switch (channelClass)
2871 {
2872 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
2873 parameters["TYPE_PREFIX"] = "u";
2874 parameters["COLOR_VAL"] = "0, 64, 192, 252";
2875 break;
2876
2877 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
2878 parameters["TYPE_PREFIX"] = "i";
2879 parameters["COLOR_VAL"] = "0, 32, 100, 124";
2880 break;
2881
2882 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
2883 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
2884 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
2885 parameters["TYPE_PREFIX"] = "";
2886 parameters["COLOR_VAL"] = "0.0, 0.4, 0.8, 1.0";
2887 break;
2888
2889 default:
2890 DE_FATAL("Unknown channel class");
2891 }
2892
2893 // parts of fragment shader for second subpass - Vulkan introduced a new uniform type and syntax to glsl for input attachments
2894 const tcu::StringTemplate subpassLayoutTemplate("layout (input_attachment_index = ${INDEX}, set = 0, binding = ${INDEX}) uniform ${TYPE_PREFIX}subpassInput i_color${INDEX};\n");
2895 const tcu::StringTemplate subpassFBodyTemplate("\to_color${INDEX} = subpassLoad(i_color${INDEX})*0.5 + subpassLoad(i_color${MIX_INDEX})*0.25;\n");
2896 const tcu::StringTemplate subpassIBodyTemplate("\to_color${INDEX} = subpassLoad(i_color${INDEX}) / 2 + subpassLoad(i_color${MIX_INDEX}) / 4;\n");
2897
2898 bool selectIBody = isIntFormat(config.format) || isUintFormat(config.format);
2899 const tcu::StringTemplate& subpassBodyTemplate = selectIBody ? subpassIBodyTemplate : subpassFBodyTemplate;
2900
2901 std::string sp0layoutDefinitions = "";
2902 std::string sp0shaderBody = "";
2903 std::string sp1inLayoutDefinitions = "";
2904 std::string sp1outLayoutDefinitions = "";
2905 std::string sp1shaderBody = "";
2906
2907 deUint32 halfAttachments = config.attachmentCount / 2;
2908 for (deUint32 attIdx = 0; attIdx < config.attachmentCount; ++attIdx)
2909 {
2910 parameters["INDEX"] = de::toString(attIdx);
2911
2912 sp0layoutDefinitions += genericLayoutTemplate.specialize(parameters);
2913 sp0shaderBody += genericBodyTemplate.specialize(parameters);
2914
2915 sp1inLayoutDefinitions += subpassLayoutTemplate.specialize(parameters);
2916 if (attIdx < halfAttachments)
2917 {
2918 // we are combining pairs of input attachments to produce half the number of outputs
2919 parameters["MIX_INDEX"] = de::toString(halfAttachments + attIdx);
2920 sp1outLayoutDefinitions += genericLayoutTemplate.specialize(parameters);
2921 sp1shaderBody += subpassBodyTemplate.specialize(parameters);
2922 }
2923 }
2924
2925 // construct fragment shaders for subpass1 and subpass2; note that there
2926 // is different shader definition depending on number of attachments
2927 std::string nameBase = "quad-frag-sp";
2928 std::string namePostfix = de::toString(config.attachmentCount);
2929 parameters["LAYOUT"] = sp0layoutDefinitions;
2930 parameters["BODY"] = sp0shaderBody;
2931 dst.glslSources.add(nameBase + "0-" + namePostfix) << glu::FragmentSource(fragTemplate.specialize(parameters));
2932 parameters["LAYOUT"] = sp1inLayoutDefinitions + sp1outLayoutDefinitions;
2933 parameters["BODY"] = sp1shaderBody;
2934 dst.glslSources.add(nameBase + "1-" + namePostfix) << glu::FragmentSource(fragTemplate.specialize(parameters));
2935 }
2936 }
2937 };
2938
2939 template<class TestConfigType>
checkSupport(Context& context, TestConfigType config)2940 void checkSupport(Context& context, TestConfigType config)
2941 {
2942 if (config.layerCount > 1)
2943 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
2944
2945 if (config.groupParams->renderingType == RENDERING_TYPE_RENDERPASS2)
2946 context.requireDeviceFunctionality("VK_KHR_create_renderpass2");
2947
2948 if (config.groupParams->renderingType == RENDERING_TYPE_DYNAMIC_RENDERING)
2949 context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
2950
2951 #ifndef CTS_USES_VULKANSC
2952 if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
2953 !context.getPortabilitySubsetFeatures().multisampleArrayImage &&
2954 (config.sampleCount != VK_SAMPLE_COUNT_1_BIT) && (config.layerCount != 1))
2955 {
2956 TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Implementation does not support image array with multiple samples per texel");
2957 }
2958 #endif // CTS_USES_VULKANSC
2959
2960 const InstanceInterface& vki = context.getInstanceInterface();
2961 vk::VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
2962 const vk::VkPhysicalDeviceProperties properties = vk::getPhysicalDeviceProperties(vki, physicalDevice);
2963
2964 if (config.attachmentCount > properties.limits.maxColorAttachments)
2965 TCU_THROW(NotSupportedError, "Required number of color attachments not supported.");
2966 }
2967
formatToName(VkFormat format)2968 std::string formatToName (VkFormat format)
2969 {
2970 const std::string formatStr = de::toString(format);
2971 const std::string prefix = "VK_FORMAT_";
2972
2973 DE_ASSERT(formatStr.substr(0, prefix.length()) == prefix);
2974
2975 return de::toLower(formatStr.substr(prefix.length()));
2976 }
2977
initTests(tcu::TestCaseGroup* group, const SharedGroupParams groupParams)2978 void initTests (tcu::TestCaseGroup* group, const SharedGroupParams groupParams)
2979 {
2980 static const VkFormat formats[] =
2981 {
2982 VK_FORMAT_R5G6B5_UNORM_PACK16,
2983 VK_FORMAT_R8_UNORM,
2984 VK_FORMAT_R8_SNORM,
2985 VK_FORMAT_R8_UINT,
2986 VK_FORMAT_R8_SINT,
2987 VK_FORMAT_R8G8_UNORM,
2988 VK_FORMAT_R8G8_SNORM,
2989 VK_FORMAT_R8G8_UINT,
2990 VK_FORMAT_R8G8_SINT,
2991 VK_FORMAT_R8G8B8A8_UNORM,
2992 VK_FORMAT_R8G8B8A8_SNORM,
2993 VK_FORMAT_R8G8B8A8_UINT,
2994 VK_FORMAT_R8G8B8A8_SINT,
2995 VK_FORMAT_R8G8B8A8_SRGB,
2996 VK_FORMAT_A8B8G8R8_UNORM_PACK32,
2997 VK_FORMAT_A8B8G8R8_SNORM_PACK32,
2998 VK_FORMAT_A8B8G8R8_UINT_PACK32,
2999 VK_FORMAT_A8B8G8R8_SINT_PACK32,
3000 VK_FORMAT_A8B8G8R8_SRGB_PACK32,
3001 VK_FORMAT_B8G8R8A8_UNORM,
3002 VK_FORMAT_B8G8R8A8_SRGB,
3003 VK_FORMAT_A2R10G10B10_UNORM_PACK32,
3004 VK_FORMAT_A2B10G10R10_UNORM_PACK32,
3005 VK_FORMAT_A2B10G10R10_UINT_PACK32,
3006 VK_FORMAT_R16_UNORM,
3007 VK_FORMAT_R16_SNORM,
3008 VK_FORMAT_R16_UINT,
3009 VK_FORMAT_R16_SINT,
3010 VK_FORMAT_R16_SFLOAT,
3011 VK_FORMAT_R16G16_UNORM,
3012 VK_FORMAT_R16G16_SNORM,
3013 VK_FORMAT_R16G16_UINT,
3014 VK_FORMAT_R16G16_SINT,
3015 VK_FORMAT_R16G16_SFLOAT,
3016 VK_FORMAT_R16G16B16A16_UNORM,
3017 VK_FORMAT_R16G16B16A16_SNORM,
3018 VK_FORMAT_R16G16B16A16_UINT,
3019 VK_FORMAT_R16G16B16A16_SINT,
3020 VK_FORMAT_R16G16B16A16_SFLOAT,
3021 VK_FORMAT_R32_UINT,
3022 VK_FORMAT_R32_SINT,
3023 VK_FORMAT_R32_SFLOAT,
3024 VK_FORMAT_R32G32_UINT,
3025 VK_FORMAT_R32G32_SINT,
3026 VK_FORMAT_R32G32_SFLOAT,
3027 VK_FORMAT_R32G32B32A32_UINT,
3028 VK_FORMAT_R32G32B32A32_SINT,
3029 VK_FORMAT_R32G32B32A32_SFLOAT,
3030 VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16,
3031 };
3032 const deUint32 sampleCounts[] =
3033 {
3034 2u, 4u, 8u
3035 };
3036 const deUint32 layerCounts[] =
3037 {
3038 1u, 3u, 6u
3039 };
3040 const deUint32 resolveLevels[] =
3041 {
3042 2u, 3u, 4u
3043 };
3044 tcu::TestContext& testCtx (group->getTestContext());
3045
3046 for (size_t layerCountNdx = 0; layerCountNdx < DE_LENGTH_OF_ARRAY(layerCounts); layerCountNdx++)
3047 {
3048 const deUint32 layerCount (layerCounts[layerCountNdx]);
3049 const std::string layerGroupName ("layers_" + de::toString(layerCount));
3050 de::MovePtr<tcu::TestCaseGroup> layerGroup (new tcu::TestCaseGroup(testCtx, layerGroupName.c_str(), layerGroupName.c_str()));
3051
3052 for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
3053 {
3054 const VkFormat format (formats[formatNdx]);
3055 const std::string formatName (formatToName(format));
3056 de::MovePtr<tcu::TestCaseGroup> formatGroup (new tcu::TestCaseGroup(testCtx, formatName.c_str(), formatName.c_str()));
3057
3058 for (size_t sampleCountNdx = 0; sampleCountNdx < DE_LENGTH_OF_ARRAY(sampleCounts); sampleCountNdx++)
3059 {
3060 const deUint32 sampleCount(sampleCounts[sampleCountNdx]);
3061
3062 // Skip this test as it is rather slow
3063 if (layerCount == 6 && sampleCount == 8)
3064 continue;
3065
3066 // Reduce number of tests for dynamic rendering cases where secondary command buffer is used
3067 if (groupParams->useSecondaryCmdBuffer && ( (sampleCount > 2u) || (layerCount > 3u) ))
3068 continue;
3069
3070 std::string testName ("samples_" + de::toString(sampleCount));
3071 const TestConfig testConfig
3072 {
3073 RESOLVE,
3074 format,
3075 sampleCount,
3076 layerCount,
3077 4u,
3078 32u,
3079 32u,
3080 groupParams
3081 };
3082
3083 formatGroup->addChild(new InstanceFactory1WithSupport<MultisampleRenderPassTestInstance, TestConfig, FunctionSupport1<TestConfig>, Programs>(testCtx, tcu::NODETYPE_SELF_VALIDATE, testName.c_str(), testName.c_str(), testConfig, typename FunctionSupport1<TestConfig>::Args(checkSupport, testConfig)));
3084
3085 for (deUint32 resolveLevel : resolveLevels)
3086 {
3087 const TestConfig2 testConfig2(testConfig, resolveLevel);
3088 std::string resolveLevelTestNameStr(testName + "_resolve_level_" + de::toString(resolveLevel));
3089 const char* resolveLevelTestName = resolveLevelTestNameStr.c_str();
3090
3091 formatGroup->addChild(new InstanceFactory1WithSupport<MultisampleRenderPassResolveLevelTestInstance, TestConfig2, FunctionSupport1<TestConfig2>, Programs>(testCtx, tcu::NODETYPE_SELF_VALIDATE, resolveLevelTestName, resolveLevelTestName, testConfig2, typename FunctionSupport1<TestConfig2>::Args(checkSupport, testConfig2)));
3092
3093 // Reduce number of tests for dynamic rendering cases where secondary command buffer is used
3094 if (groupParams->useSecondaryCmdBuffer)
3095 break;
3096 }
3097
3098 // MaxAttachmenstsRenderPassTest is ment to test extreme cases where applications might consume all available on-chip
3099 // memory. This is achieved by using maxColorAttachments attachments and two subpasses, but during test creation we
3100 // dont know what is the maximal number of attachments (spirv tools are not available on all platforms) so we cant
3101 // construct shaders during test execution. To be able to test this we need to execute tests for all available
3102 // numbers of attachments despite the fact that we are only interested in the maximal number; test construction code
3103 // assumes that the number of attachments is power of two
3104 if ((groupParams->renderingType != RENDERING_TYPE_DYNAMIC_RENDERING) && (layerCount == 1))
3105 {
3106 for (deUint32 power = 2; power < 5; ++power)
3107 {
3108 deUint32 attachmentCount = 1 << power;
3109 std::string maxAttName = "max_attachments_" + de::toString(attachmentCount) + "_" + testName;
3110
3111 TestConfig maxAttachmentsTestConfig = testConfig;
3112 maxAttachmentsTestConfig.testType = MAX_ATTACHMENTS;
3113 maxAttachmentsTestConfig.attachmentCount = attachmentCount;
3114
3115 formatGroup->addChild(new InstanceFactory1WithSupport<MaxAttachmenstsRenderPassTestInstance, TestConfig, FunctionSupport1<TestConfig>, Programs>(testCtx, tcu::NODETYPE_SELF_VALIDATE, maxAttName.c_str(), maxAttName.c_str(), maxAttachmentsTestConfig, typename FunctionSupport1<TestConfig>::Args(checkSupport, maxAttachmentsTestConfig)));
3116 }
3117
3118 {
3119 std::string compatibilityTestName = "compatibility_" + testName;
3120
3121 TestConfig compatibilityTestConfig = testConfig;
3122 compatibilityTestConfig.testType = COMPATIBILITY;
3123 compatibilityTestConfig.attachmentCount = 1;
3124
3125 formatGroup->addChild(new InstanceFactory1WithSupport<MultisampleRenderPassTestInstance, TestConfig, FunctionSupport1<TestConfig>, Programs>(testCtx, tcu::NODETYPE_SELF_VALIDATE, compatibilityTestName.c_str(), compatibilityTestName.c_str(), compatibilityTestConfig, typename FunctionSupport1<TestConfig>::Args(checkSupport, compatibilityTestConfig)));
3126 }
3127 }
3128 }
3129
3130 if (layerCount == 1)
3131 group->addChild(formatGroup.release());
3132 else
3133 layerGroup->addChild(formatGroup.release());
3134 }
3135
3136 if (layerCount != 1)
3137 group->addChild(layerGroup.release());
3138 }
3139 }
3140
3141 } // anonymous
3142
createRenderPassMultisampleResolveTests(tcu::TestContext& testCtx, const renderpass::SharedGroupParams groupParams)3143 tcu::TestCaseGroup* createRenderPassMultisampleResolveTests (tcu::TestContext& testCtx, const renderpass::SharedGroupParams groupParams)
3144 {
3145 return createTestGroup(testCtx, "multisample_resolve", "Multisample render pass resolve tests", initTests, groupParams);
3146 }
3147
createRenderPass2MultisampleResolveTests(tcu::TestContext& testCtx, const renderpass::SharedGroupParams groupParams)3148 tcu::TestCaseGroup* createRenderPass2MultisampleResolveTests (tcu::TestContext& testCtx, const renderpass::SharedGroupParams groupParams)
3149 {
3150 return createTestGroup(testCtx, "multisample_resolve", "Multisample render pass resolve tests", initTests, groupParams);
3151 }
3152
createDynamicRenderingMultisampleResolveTests(tcu::TestContext& testCtx, const renderpass::SharedGroupParams groupParams)3153 tcu::TestCaseGroup* createDynamicRenderingMultisampleResolveTests (tcu::TestContext& testCtx, const renderpass::SharedGroupParams groupParams)
3154 {
3155 return createTestGroup(testCtx, "multisample_resolve", "Multisample dynamic rendering resolve tests", initTests, groupParams);
3156 }
3157
3158 } // vkt
3159