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