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::__anon0c42d1a50111::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 for (size_t dstNdx = 0; dstNdx < m_singlesampleImages.size(); dstNdx++)
803 {
804 // assume that buffer(s) have enough memory to store desired amount of mipmaps
805 copyImageToBuffer(vkd, *commandBuffer, **m_singlesampleImages[dstNdx], **m_buffers[dstNdx], m_format,
806 tcu::IVec2((1u << m_renderLevel) * m_width, (1u << m_renderLevel) * m_height), m_renderLevel,
807 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, totalLayers());
808 }
809
810 endCommandBuffer(vkd, *commandBuffer);
811
812 submitCommandsAndWait(vkd, device, m_context.getUniversalQueue(), *commandBuffer);
813
814 for (size_t memoryBufferNdx = 0; memoryBufferNdx < m_bufferMemory.size(); memoryBufferNdx++)
815 invalidateMappedMemoryRange(vkd, device, m_bufferMemory[memoryBufferNdx]->getMemory(), 0u, VK_WHOLE_SIZE);
816 }
817
submitDynamicRendering(void)818 void MultisampleRenderPassTestInstance::submitDynamicRendering(void)
819 {
820 #ifndef CTS_USES_VULKANSC
821
822 const DeviceInterface &vkd(m_context.getDeviceInterface());
823 const VkDevice device(m_context.getDevice());
824 const Unique<VkCommandBuffer> cmdBuffer(
825 allocateCommandBuffer(vkd, device, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
826 Move<VkCommandBuffer> secCmdBuffer;
827
828 // Memory barriers between previous copies and rendering
829 std::vector<VkImageMemoryBarrier> singlesampleImageBarriers(
830 m_singlesampleImages.size(), {VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
831 DE_NULL,
832
833 VK_ACCESS_TRANSFER_READ_BIT,
834 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
835
836 VK_IMAGE_LAYOUT_UNDEFINED,
837 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
838
839 VK_QUEUE_FAMILY_IGNORED,
840 VK_QUEUE_FAMILY_IGNORED,
841
842 DE_NULL,
843 {VK_IMAGE_ASPECT_COLOR_BIT, m_renderLevel, 1u, 0u, totalLayers()}});
844 for (size_t dstNdx = 0; dstNdx < m_singlesampleImages.size(); dstNdx++)
845 singlesampleImageBarriers[dstNdx].image = **m_singlesampleImages[dstNdx];
846
847 // Memory barriers to set multisample image layout to COLOR_ATTACHMENT_OPTIMAL
848 std::vector<VkImageMemoryBarrier> multisampleImageBarriers(m_multisampleImages.size(),
849 {VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
850 DE_NULL,
851
852 0,
853 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
854
855 VK_IMAGE_LAYOUT_UNDEFINED,
856 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
857
858 VK_QUEUE_FAMILY_IGNORED,
859 VK_QUEUE_FAMILY_IGNORED,
860
861 DE_NULL,
862 {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, m_layerCount}});
863 for (size_t dstNdx = 0; dstNdx < m_multisampleImages.size(); dstNdx++)
864 multisampleImageBarriers[dstNdx].image = **m_multisampleImages[dstNdx];
865
866 VkRect2D renderArea = makeRect2D(m_width, m_height);
867 const VkClearValue clearValue = makeClearValueColor({0.0f, 0.0f, 0.0f, 1.0f});
868 std::vector<vk::VkRenderingAttachmentInfoKHR> colorAttachments(
869 m_attachmentsCount,
870 {
871 vk::VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR, // VkStructureType sType;
872 DE_NULL, // const void* pNext;
873 DE_NULL, // VkImageView imageView;
874 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout imageLayout;
875 vk::VK_RESOLVE_MODE_NONE, // VkResolveModeFlagBits resolveMode;
876 DE_NULL, // VkImageView resolveImageView;
877 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout resolveImageLayout;
878 vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp loadOp;
879 vk::VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp storeOp;
880 clearValue // VkClearValue clearValue;
881 });
882
883 for (uint32_t i = 0; i < m_attachmentsCount; ++i)
884 {
885 colorAttachments[i].imageView = **m_multisampleImageViews[i];
886 colorAttachments[i].resolveImageView = **m_singlesampleImageViews[i];
887 if (isIntFormat(m_format) || isUintFormat(m_format))
888 colorAttachments[i].resolveMode = vk::VK_RESOLVE_MODE_SAMPLE_ZERO_BIT;
889 else
890 colorAttachments[i].resolveMode = vk::VK_RESOLVE_MODE_AVERAGE_BIT;
891 }
892
893 vk::VkRenderingInfoKHR renderingInfo{
894 vk::VK_STRUCTURE_TYPE_RENDERING_INFO_KHR,
895 DE_NULL,
896 0, // VkRenderingFlagsKHR flags;
897 renderArea, // VkRect2D renderArea;
898 m_layerCount, // uint32_t layerCount;
899 0u, // uint32_t viewMask;
900 m_attachmentsCount, // uint32_t colorAttachmentCount;
901 colorAttachments.data(), // const VkRenderingAttachmentInfoKHR* pColorAttachments;
902 DE_NULL, // const VkRenderingAttachmentInfoKHR* pDepthAttachment;
903 DE_NULL, // const VkRenderingAttachmentInfoKHR* pStencilAttachment;
904 };
905
906 if (m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
907 {
908 secCmdBuffer = allocateCommandBuffer(vkd, device, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
909
910 // record secondary command buffer
911 beginSecondaryCmdBuffer(*secCmdBuffer);
912 vkd.cmdBeginRendering(*secCmdBuffer, &renderingInfo);
913 drawCommands(*secCmdBuffer, *m_renderPipeline, *m_renderPipelineLayout);
914 vkd.cmdEndRendering(*secCmdBuffer);
915
916 endCommandBuffer(vkd, *secCmdBuffer);
917
918 // record primary command buffer
919 beginCommandBuffer(vkd, *cmdBuffer);
920
921 vkd.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
922 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL,
923 (uint32_t)singlesampleImageBarriers.size(), &singlesampleImageBarriers[0]);
924 vkd.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
925 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL,
926 (uint32_t)multisampleImageBarriers.size(), &multisampleImageBarriers[0]);
927
928 vkd.cmdExecuteCommands(*cmdBuffer, 1u, &*secCmdBuffer);
929 }
930 else
931 {
932 beginCommandBuffer(vkd, *cmdBuffer);
933
934 vkd.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
935 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL,
936 (uint32_t)singlesampleImageBarriers.size(), &singlesampleImageBarriers[0]);
937 vkd.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
938 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL,
939 (uint32_t)multisampleImageBarriers.size(), &multisampleImageBarriers[0]);
940
941 vkd.cmdBeginRendering(*cmdBuffer, &renderingInfo);
942 drawCommands(*cmdBuffer, *m_renderPipeline, *m_renderPipelineLayout);
943 vkd.cmdEndRendering(*cmdBuffer);
944 }
945
946 // Memory barriers to set single-sample image layout to TRANSFER_SRC_OPTIMAL
947 {
948 std::vector<VkImageMemoryBarrier> barriers;
949
950 for (size_t dstNdx = 0; dstNdx < m_singlesampleImages.size(); dstNdx++)
951 {
952 const VkImageMemoryBarrier barrier = {VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
953 DE_NULL,
954
955 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
956 VK_ACCESS_TRANSFER_READ_BIT,
957
958 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
959 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
960
961 VK_QUEUE_FAMILY_IGNORED,
962 VK_QUEUE_FAMILY_IGNORED,
963
964 **m_singlesampleImages[dstNdx],
965 {VK_IMAGE_ASPECT_COLOR_BIT, m_renderLevel, 1u, 0u, totalLayers()}};
966
967 barriers.push_back(barrier);
968 }
969
970 vkd.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
971 VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, (uint32_t)barriers.size(),
972 &barriers[0]);
973 }
974
975 for (size_t dstNdx = 0; dstNdx < m_singlesampleImages.size(); dstNdx++)
976 {
977 // assume that buffer(s) have enough memory to store desired amount of mipmaps
978 copyImageToBuffer(vkd, *cmdBuffer, **m_singlesampleImages[dstNdx], **m_buffers[dstNdx], m_format,
979 tcu::IVec2((1u << m_renderLevel) * m_width, (1u << m_renderLevel) * m_height), m_renderLevel,
980 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, totalLayers());
981 }
982
983 endCommandBuffer(vkd, *cmdBuffer);
984
985 submitCommandsAndWait(vkd, device, m_context.getUniversalQueue(), *cmdBuffer);
986
987 for (size_t memoryBufferNdx = 0; memoryBufferNdx < m_bufferMemory.size(); memoryBufferNdx++)
988 invalidateMappedMemoryRange(vkd, device, m_bufferMemory[memoryBufferNdx]->getMemory(), 0u, VK_WHOLE_SIZE);
989
990 #endif // CTS_USES_VULKANSC
991 }
992
submitSwitch(const SharedGroupParams groupParams)993 void MultisampleRenderPassTestInstance::submitSwitch(const SharedGroupParams groupParams)
994 {
995 switch (groupParams->renderingType)
996 {
997 case RENDERING_TYPE_RENDERPASS_LEGACY:
998 submit<RenderpassSubpass1>();
999 break;
1000 case RENDERING_TYPE_RENDERPASS2:
1001 submit<RenderpassSubpass2>();
1002 break;
1003 case RENDERING_TYPE_DYNAMIC_RENDERING:
1004 submitDynamicRendering();
1005 break;
1006 default:
1007 TCU_THROW(InternalError, "Impossible");
1008 }
1009 }
1010
verify(void)1011 void MultisampleRenderPassTestInstance::verify(void)
1012 {
1013 const Vec4 errorColor(1.0f, 0.0f, 0.0f, 1.0f);
1014 const Vec4 okColor(0.0f, 1.0f, 0.0f, 1.0f);
1015 const tcu::TextureFormat format(mapVkFormat(m_format));
1016 const tcu::TextureChannelClass channelClass(tcu::getTextureChannelClass(format.type));
1017
1018 uint32_t offset(0u);
1019 uint32_t width((1u << m_renderLevel) * m_width);
1020 uint32_t height((1u << m_renderLevel) * m_height);
1021 uint32_t pixelSize(static_cast<uint32_t>(getPixelSize()));
1022 for (uint32_t level = 0; level < m_renderLevel; ++level)
1023 {
1024 offset += (width * height * pixelSize);
1025 height /= 2;
1026 width /= 2;
1027 }
1028
1029 std::vector<tcu::ConstPixelBufferAccess> accesses;
1030 for (uint32_t attachmentIdx = 0; attachmentIdx < m_attachmentsCount; ++attachmentIdx)
1031 {
1032 void *const ptr = static_cast<uint8_t *>(m_bufferMemory[attachmentIdx]->getHostPtr()) + offset;
1033 accesses.push_back(tcu::ConstPixelBufferAccess(format, m_width, m_height, totalLayers(), ptr));
1034 }
1035
1036 tcu::TextureLevel errorMask(tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), m_width,
1037 m_height, totalLayers());
1038 tcu::TestLog &log(m_context.getTestContext().getLog());
1039
1040 switch (channelClass)
1041 {
1042 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
1043 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
1044 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
1045 {
1046 const bool isAlphaOnly = isAlphaOnlyFormat(m_format);
1047 const int componentCount(isAlphaOnly ? 4 : tcu::getNumUsedChannels(format.order));
1048 bool isOk = true;
1049 float clearValue;
1050 float renderValue;
1051
1052 switch (channelClass)
1053 {
1054 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
1055 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
1056 clearValue = -1.0f;
1057 renderValue = 1.0f;
1058 break;
1059
1060 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
1061 clearValue = 0.0f;
1062 renderValue = 1.0f;
1063 break;
1064
1065 default:
1066 clearValue = 0.0f;
1067 renderValue = 0.0f;
1068 DE_FATAL("Unknown channel class");
1069 }
1070
1071 for (uint32_t z = m_baseLayer; z < totalLayers(); z++)
1072 for (uint32_t y = 0; y < m_height; y++)
1073 for (uint32_t x = 0; x < m_width; x++)
1074 {
1075 // Color has to be black if no samples were covered, white if all samples were covered or same in every attachment
1076 const Vec4 firstColor(accesses[0].getPixel(x, y, z));
1077 const Vec4 refColor(m_sampleMask == 0x0u ?
1078 Vec4((isAlphaOnly ? 0.0f : clearValue),
1079 componentCount > 1 && !isAlphaOnly ? clearValue : 0.0f,
1080 componentCount > 2 && !isAlphaOnly ? clearValue : 0.0f,
1081 componentCount > 3 ? clearValue : 1.0f) :
1082 m_sampleMask == ((0x1u << m_sampleCount) - 1u) ?
1083 Vec4((isAlphaOnly ? 0.0f : renderValue),
1084 componentCount > 1 && !isAlphaOnly ? renderValue : 0.0f,
1085 componentCount > 2 && !isAlphaOnly ? renderValue : 0.0f,
1086 componentCount > 3 ? renderValue : 1.0f) :
1087 firstColor);
1088
1089 errorMask.getAccess().setPixel(okColor, x, y, z);
1090
1091 for (size_t attachmentNdx = 0; attachmentNdx < m_attachmentsCount; attachmentNdx++)
1092 {
1093 const Vec4 color(accesses[attachmentNdx].getPixel(x, y, z));
1094
1095 if (refColor != color)
1096 {
1097 isOk = false;
1098 errorMask.getAccess().setPixel(errorColor, x, y, z);
1099 break;
1100 }
1101 }
1102
1103 {
1104 const Vec4 old = m_sum.getAccess().getPixel(x, y, z);
1105 m_sum.getAccess().setPixel(
1106 old + (tcu::isSRGB(format) ? tcu::sRGBToLinear(firstColor) : firstColor), x, y, z);
1107
1108 const Vec4 oldSrgb = m_sumSrgb.getAccess().getPixel(x, y, z);
1109 m_sumSrgb.getAccess().setPixel(oldSrgb + firstColor, x, y, z);
1110 }
1111 }
1112
1113 if (!isOk)
1114 {
1115 const std::string sectionName("ResolveVerifyWithMask" + de::toString(m_sampleMask));
1116 const tcu::ScopedLogSection section(log, sectionName, sectionName);
1117
1118 for (size_t attachmentNdx = 0; attachmentNdx < m_attachmentsCount; attachmentNdx++)
1119 logImage(std::string("Attachment") + de::toString(attachmentNdx), accesses[attachmentNdx]);
1120
1121 logImage("ErrorMask", errorMask.getAccess());
1122
1123 if (m_sampleMask == 0x0u)
1124 {
1125 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Empty sample mask didn't produce all "
1126 << clearValue << " pixels" << tcu::TestLog::EndMessage;
1127 m_resultCollector.fail("Empty sample mask didn't produce correct pixel values");
1128 }
1129 else if (m_sampleMask == ((0x1u << m_sampleCount) - 1u))
1130 {
1131 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Full sample mask didn't produce all "
1132 << renderValue << " pixels" << tcu::TestLog::EndMessage;
1133 m_resultCollector.fail("Full sample mask didn't produce correct pixel values");
1134 }
1135 else
1136 {
1137 m_context.getTestContext().getLog()
1138 << tcu::TestLog::Message << "Resolve is inconsistent between attachments"
1139 << tcu::TestLog::EndMessage;
1140 m_resultCollector.fail("Resolve is inconsistent between attachments");
1141 }
1142 }
1143 break;
1144 }
1145
1146 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
1147 {
1148 const int componentCount(tcu::getNumUsedChannels(format.order));
1149 const UVec4 bitDepth(tcu::getTextureFormatBitDepth(format).cast<uint32_t>());
1150 const UVec4 renderValue(tcu::select((UVec4(1u) << tcu::min(UVec4(8u), bitDepth)) - UVec4(1u),
1151 UVec4(0u, 0u, 0u, 1u),
1152 tcu::lessThan(IVec4(0, 1, 2, 3), IVec4(componentCount))));
1153 const UVec4 clearValue(
1154 tcu::select(UVec4(0u), UVec4(0u, 0u, 0u, 1u), tcu::lessThan(IVec4(0, 1, 2, 3), IVec4(componentCount))));
1155 bool unexpectedValues = false;
1156 bool inconsistentComponents = false;
1157 bool inconsistentAttachments = false;
1158
1159 for (uint32_t z = m_baseLayer; z < totalLayers(); z++)
1160 for (uint32_t y = 0; y < m_height; y++)
1161 for (uint32_t x = 0; x < m_width; x++)
1162 {
1163 // Color has to be all zeros if no samples were covered, all 255 if all samples were covered or consistent across all attachments
1164 const UVec4 refColor(m_sampleMask == 0x0u ? clearValue :
1165 m_sampleMask == ((0x1u << m_sampleCount) - 1u) ?
1166 renderValue :
1167 accesses[0].getPixelUint(x, y, z));
1168 bool isOk = true;
1169
1170 // If reference value was taken from first attachment, check that it is valid value i.e. clear or render value
1171 if (m_sampleMask != 0x0u && m_sampleMask != ((0x1u << m_sampleCount) - 1u))
1172 {
1173 // Each component must be resolved same way
1174 const BVec4 isRenderValue(refColor == renderValue);
1175 const BVec4 isClearValue(refColor == clearValue);
1176 const bool unexpectedValue(
1177 tcu::anyNotEqual(tcu::logicalOr(isRenderValue, isClearValue), BVec4(true)));
1178 const bool inconsistentComponent(
1179 !(tcu::allEqual(isRenderValue, BVec4(true)) || tcu::allEqual(isClearValue, BVec4(true))));
1180
1181 unexpectedValues |= unexpectedValue;
1182 inconsistentComponents |= inconsistentComponent;
1183
1184 if (unexpectedValue || inconsistentComponent)
1185 isOk = false;
1186 }
1187
1188 for (size_t attachmentNdx = 0; attachmentNdx < m_attachmentsCount; attachmentNdx++)
1189 {
1190 const UVec4 color(accesses[attachmentNdx].getPixelUint(x, y, z));
1191
1192 if (refColor != color)
1193 {
1194 isOk = false;
1195 inconsistentAttachments = true;
1196 break;
1197 }
1198 }
1199
1200 errorMask.getAccess().setPixel((isOk ? okColor : errorColor), x, y, z);
1201 }
1202
1203 if (unexpectedValues || inconsistentComponents || inconsistentAttachments)
1204 {
1205 const std::string sectionName("ResolveVerifyWithMask" + de::toString(m_sampleMask));
1206 const tcu::ScopedLogSection section(log, sectionName, sectionName);
1207
1208 for (size_t attachmentNdx = 0; attachmentNdx < m_attachmentsCount; attachmentNdx++)
1209 logImage(std::string("Attachment") + de::toString(attachmentNdx), accesses[attachmentNdx]);
1210
1211 logImage("ErrorMask", errorMask.getAccess());
1212
1213 if (m_sampleMask == 0x0u)
1214 {
1215 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Empty sample mask didn't produce all "
1216 << clearValue << " pixels" << tcu::TestLog::EndMessage;
1217 m_resultCollector.fail("Empty sample mask didn't produce correct pixels");
1218 }
1219 else if (m_sampleMask == ((0x1u << m_sampleCount) - 1u))
1220 {
1221 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Full sample mask didn't produce all "
1222 << renderValue << " pixels" << tcu::TestLog::EndMessage;
1223 m_resultCollector.fail("Full sample mask didn't produce correct pixels");
1224 }
1225 else
1226 {
1227 if (unexpectedValues)
1228 {
1229 m_context.getTestContext().getLog()
1230 << tcu::TestLog::Message << "Resolve produced unexpected values i.e. not " << clearValue
1231 << " or " << renderValue << tcu::TestLog::EndMessage;
1232 m_resultCollector.fail("Resolve produced unexpected values");
1233 }
1234
1235 if (inconsistentComponents)
1236 {
1237 m_context.getTestContext().getLog()
1238 << tcu::TestLog::Message
1239 << "Different components of attachment were resolved to different values."
1240 << tcu::TestLog::EndMessage;
1241 m_resultCollector.fail("Different components of attachment were resolved to different values.");
1242 }
1243
1244 if (inconsistentAttachments)
1245 {
1246 m_context.getTestContext().getLog()
1247 << tcu::TestLog::Message << "Different attachments were resolved to different values."
1248 << tcu::TestLog::EndMessage;
1249 m_resultCollector.fail("Different attachments were resolved to different values.");
1250 }
1251 }
1252 }
1253 break;
1254 }
1255
1256 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
1257 {
1258 const int componentCount(tcu::getNumUsedChannels(format.order));
1259 const IVec4 bitDepth(tcu::getTextureFormatBitDepth(format));
1260 const IVec4 renderValue(tcu::select((IVec4(1) << (tcu::min(IVec4(8), bitDepth) - IVec4(1))) - IVec4(1),
1261 IVec4(0, 0, 0, 1),
1262 tcu::lessThan(IVec4(0, 1, 2, 3), IVec4(componentCount))));
1263 const IVec4 clearValue(tcu::select(-(IVec4(1) << (tcu::min(IVec4(8), bitDepth) - IVec4(1))), IVec4(0, 0, 0, 1),
1264 tcu::lessThan(IVec4(0, 1, 2, 3), IVec4(componentCount))));
1265 bool unexpectedValues = false;
1266 bool inconsistentComponents = false;
1267 bool inconsistentAttachments = false;
1268
1269 for (uint32_t z = m_baseLayer; z < totalLayers(); z++)
1270 for (uint32_t y = 0; y < m_height; y++)
1271 for (uint32_t x = 0; x < m_width; x++)
1272 {
1273 // Color has to be all zeros if no samples were covered, all 255 if all samples were covered or consistent across all attachments
1274 const IVec4 refColor(m_sampleMask == 0x0u ? clearValue :
1275 m_sampleMask == ((0x1u << m_sampleCount) - 1u) ?
1276 renderValue :
1277 accesses[0].getPixelInt(x, y, z));
1278 bool isOk = true;
1279
1280 // If reference value was taken from first attachment, check that it is valid value i.e. clear or render value
1281 if (m_sampleMask != 0x0u && m_sampleMask != ((0x1u << m_sampleCount) - 1u))
1282 {
1283 // Each component must be resolved same way
1284 const BVec4 isRenderValue(refColor == renderValue);
1285 const BVec4 isClearValue(refColor == clearValue);
1286 const bool unexpectedValue(
1287 tcu::anyNotEqual(tcu::logicalOr(isRenderValue, isClearValue), BVec4(true)));
1288 const bool inconsistentComponent(
1289 !(tcu::allEqual(isRenderValue, BVec4(true)) || tcu::allEqual(isClearValue, BVec4(true))));
1290
1291 unexpectedValues |= unexpectedValue;
1292 inconsistentComponents |= inconsistentComponent;
1293
1294 if (unexpectedValue || inconsistentComponent)
1295 isOk = false;
1296 }
1297
1298 for (size_t attachmentNdx = 0; attachmentNdx < m_attachmentsCount; attachmentNdx++)
1299 {
1300 const IVec4 color(accesses[attachmentNdx].getPixelInt(x, y, z));
1301
1302 if (refColor != color)
1303 {
1304 isOk = false;
1305 inconsistentAttachments = true;
1306 break;
1307 }
1308 }
1309
1310 errorMask.getAccess().setPixel((isOk ? okColor : errorColor), x, y, z);
1311 }
1312
1313 if (unexpectedValues || inconsistentComponents || inconsistentAttachments)
1314 {
1315 const std::string sectionName("ResolveVerifyWithMask" + de::toString(m_sampleMask));
1316 const tcu::ScopedLogSection section(log, sectionName, sectionName);
1317
1318 for (size_t attachmentNdx = 0; attachmentNdx < m_attachmentsCount; attachmentNdx++)
1319 logImage(std::string("Attachment") + de::toString(attachmentNdx), accesses[attachmentNdx]);
1320
1321 logImage("ErrorMask", errorMask.getAccess());
1322
1323 if (m_sampleMask == 0x0u)
1324 {
1325 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Empty sample mask didn't produce all "
1326 << clearValue << " pixels" << tcu::TestLog::EndMessage;
1327 m_resultCollector.fail("Empty sample mask didn't produce correct pixels");
1328 }
1329 else if (m_sampleMask == ((0x1u << m_sampleCount) - 1u))
1330 {
1331 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Full sample mask didn't produce all "
1332 << renderValue << " pixels" << tcu::TestLog::EndMessage;
1333 m_resultCollector.fail("Full sample mask didn't produce correct pixels");
1334 }
1335 else
1336 {
1337 if (unexpectedValues)
1338 {
1339 m_context.getTestContext().getLog()
1340 << tcu::TestLog::Message << "Resolve produced unexpected values i.e. not " << clearValue
1341 << " or " << renderValue << tcu::TestLog::EndMessage;
1342 m_resultCollector.fail("Resolve produced unexpected values");
1343 }
1344
1345 if (inconsistentComponents)
1346 {
1347 m_context.getTestContext().getLog()
1348 << tcu::TestLog::Message
1349 << "Different components of attachment were resolved to different values."
1350 << tcu::TestLog::EndMessage;
1351 m_resultCollector.fail("Different components of attachment were resolved to different values.");
1352 }
1353
1354 if (inconsistentAttachments)
1355 {
1356 m_context.getTestContext().getLog()
1357 << tcu::TestLog::Message << "Different attachments were resolved to different values."
1358 << tcu::TestLog::EndMessage;
1359 m_resultCollector.fail("Different attachments were resolved to different values.");
1360 }
1361 }
1362 }
1363 break;
1364 }
1365
1366 default:
1367 DE_FATAL("Unknown channel class");
1368 }
1369 }
1370
iterate(void)1371 tcu::TestStatus MultisampleRenderPassTestInstance::iterate(void)
1372 {
1373 if (m_sampleMask == 0u)
1374 {
1375 const tcu::TextureFormat format(mapVkFormat(m_format));
1376 const tcu::TextureChannelClass channelClass(tcu::getTextureChannelClass(format.type));
1377 tcu::TestLog &log(m_context.getTestContext().getLog());
1378
1379 switch (channelClass)
1380 {
1381 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
1382 log << TestLog::Message
1383 << "Clearing target to zero and rendering 255 pixels with every possible sample mask"
1384 << TestLog::EndMessage;
1385 break;
1386
1387 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
1388 log << TestLog::Message
1389 << "Clearing target to -128 and rendering 127 pixels with every possible sample mask"
1390 << TestLog::EndMessage;
1391 break;
1392
1393 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
1394 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
1395 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
1396 log << TestLog::Message
1397 << "Clearing target to black and rendering white pixels with every possible sample mask"
1398 << TestLog::EndMessage;
1399 break;
1400
1401 default:
1402 DE_FATAL("Unknown channel class");
1403 }
1404 }
1405
1406 submitSwitch(m_groupParams);
1407 verify();
1408
1409 if (m_sampleMask == ((0x1u << m_sampleCount) - 1u))
1410 {
1411 const tcu::TextureFormat format(mapVkFormat(m_format));
1412 const tcu::TextureChannelClass channelClass(tcu::getTextureChannelClass(format.type));
1413 const Vec4 threshold(getFormatThreshold());
1414 tcu::TestLog &log(m_context.getTestContext().getLog());
1415
1416 if (channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT ||
1417 channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT ||
1418 channelClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT)
1419 {
1420 const bool isAlphaOnly = isAlphaOnlyFormat(m_format);
1421 const int componentCount(isAlphaOnly ? 4 : tcu::getNumUsedChannels(format.order));
1422 const Vec4 errorColor(1.0f, 0.0f, 0.0f, 1.0f);
1423 const Vec4 okColor(0.0f, 1.0f, 0.0f, 1.0f);
1424 tcu::TextureLevel errorMask(tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8),
1425 m_width, m_height, totalLayers());
1426 bool isOk = true;
1427 Vec4 maxDiff(0.0f);
1428 Vec4 expectedAverage;
1429
1430 switch (channelClass)
1431 {
1432 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
1433 {
1434 expectedAverage =
1435 Vec4((isAlphaOnly ? 0.0f : 0.5f), componentCount > 1 && !isAlphaOnly ? 0.5f : 0.0f,
1436 componentCount > 2 && !isAlphaOnly ? 0.5f : 0.0f, componentCount > 3 ? 0.5f : 1.0f);
1437 break;
1438 }
1439
1440 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
1441 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
1442 {
1443 expectedAverage = Vec4(0.0f, 0.0f, 0.0f, componentCount > 3 ? 0.0f : 1.0f);
1444 break;
1445 }
1446
1447 default:
1448 DE_FATAL("Unknown channel class");
1449 }
1450
1451 for (uint32_t z = m_baseLayer; z < totalLayers(); z++)
1452 for (uint32_t y = 0; y < m_height; y++)
1453 for (uint32_t x = 0; x < m_width; x++)
1454 {
1455 const Vec4 sum(m_sum.getAccess().getPixel(x, y, z));
1456 const Vec4 average(sum / Vec4((float)(0x1u << m_sampleCount)));
1457 const Vec4 diff(tcu::abs(average - expectedAverage));
1458
1459 m_sum.getAccess().setPixel(average, x, y, z);
1460 errorMask.getAccess().setPixel(okColor, x, y, z);
1461
1462 bool failThreshold;
1463
1464 if (!tcu::isSRGB(format))
1465 {
1466 failThreshold = (diff[0] > threshold.x() || diff[1] > threshold.y() ||
1467 diff[2] > threshold.z() || diff[3] > threshold.w());
1468 }
1469 else
1470 {
1471 const Vec4 sumSrgb(m_sumSrgb.getAccess().getPixel(x, y, z));
1472 const Vec4 averageSrgb(sumSrgb / Vec4((float)(0x1u << m_sampleCount)));
1473 const Vec4 diffSrgb(tcu::abs(averageSrgb - expectedAverage));
1474
1475 m_sumSrgb.getAccess().setPixel(averageSrgb, x, y, z);
1476
1477 // Spec doesn't restrict implementation to downsample in linear color space. So, comparing both non linear and
1478 // linear diff's in case of srgb formats.
1479 failThreshold = ((diff[0] > threshold.x() || diff[1] > threshold.y() ||
1480 diff[2] > threshold.z() || diff[3] > threshold.w()) &&
1481 (diffSrgb[0] > threshold.x() || diffSrgb[1] > threshold.y() ||
1482 diffSrgb[2] > threshold.z() || diffSrgb[3] > threshold.w()));
1483 }
1484
1485 if (failThreshold)
1486 {
1487 isOk = false;
1488 maxDiff = tcu::max(maxDiff, diff);
1489 errorMask.getAccess().setPixel(errorColor, x, y, z);
1490 }
1491 }
1492
1493 log << TestLog::Image("Average resolved values in attachment 0", "Average resolved values in attachment 0",
1494 m_sum);
1495
1496 if (!isOk)
1497 {
1498 std::stringstream message;
1499
1500 m_context.getTestContext().getLog() << tcu::LogImage("ErrorMask", "ErrorMask", errorMask.getAccess());
1501
1502 message << "Average resolved values differ from expected average values by more than ";
1503
1504 switch (componentCount)
1505 {
1506 case 1:
1507 message << threshold.x();
1508 break;
1509 case 2:
1510 message << "vec2" << Vec2(threshold.x(), threshold.y());
1511 break;
1512 case 3:
1513 message << "vec3" << Vec3(threshold.x(), threshold.y(), threshold.z());
1514 break;
1515 default:
1516 message << "vec4" << threshold;
1517 }
1518
1519 message << ". Max diff " << maxDiff;
1520 log << TestLog::Message << message.str() << TestLog::EndMessage;
1521
1522 m_resultCollector.fail("Average resolved values differ from expected average values");
1523 }
1524 }
1525
1526 return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage());
1527 }
1528 else
1529 {
1530 m_sampleMask++;
1531 return tcu::TestStatus::incomplete();
1532 }
1533 }
1534
1535 template <typename RenderPassTrait>
createRenderPass(bool usedResolveAttachment)1536 Move<VkRenderPass> MultisampleRenderPassTestInstance::createRenderPass(bool usedResolveAttachment)
1537 {
1538 // make name for RenderPass1Trait or RenderPass2Trait shorter
1539 typedef RenderPassTrait RPT;
1540 typedef typename RPT::AttDesc AttDesc;
1541 typedef typename RPT::AttRef AttRef;
1542 typedef typename RPT::SubpassDesc SubpassDesc;
1543 typedef typename RPT::RenderPassCreateInfo RenderPassCreateInfo;
1544
1545 const DeviceInterface &vkd = m_context.getDeviceInterface();
1546 VkDevice device = m_context.getDevice();
1547 std::vector<AttDesc> attachments;
1548 std::vector<AttRef> colorAttachmentRefs;
1549 std::vector<AttRef> resolveAttachmentRefs;
1550
1551 for (size_t attachmentNdx = 0; attachmentNdx < m_attachmentsCount; attachmentNdx++)
1552 {
1553 {
1554 const AttDesc multisampleAttachment(
1555 // sType
1556 DE_NULL, // pNext
1557 0u, // flags
1558 m_format, // format
1559 m_sampleCount, // samples
1560 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // loadOp
1561 VK_ATTACHMENT_STORE_OP_DONT_CARE, // storeOp
1562 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // stencilLoadOp
1563 VK_ATTACHMENT_STORE_OP_DONT_CARE, // stencilStoreOp
1564 VK_IMAGE_LAYOUT_UNDEFINED, // initialLayout
1565 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // finalLayout
1566 );
1567 const AttRef attachmentRef(
1568 // sType
1569 DE_NULL, // pNext
1570 (uint32_t)attachments.size(), // attachment
1571 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // layout
1572 0u // aspectMask
1573 );
1574 colorAttachmentRefs.push_back(attachmentRef);
1575 attachments.push_back(multisampleAttachment);
1576 }
1577 {
1578 const AttDesc singlesampleAttachment(
1579 // sType
1580 DE_NULL, // pNext
1581 0u, // flags
1582 m_format, // format
1583 VK_SAMPLE_COUNT_1_BIT, // samples
1584 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // loadOp
1585 VK_ATTACHMENT_STORE_OP_STORE, // storeOp
1586 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // stencilLoadOp
1587 VK_ATTACHMENT_STORE_OP_DONT_CARE, // stencilStoreOp
1588 VK_IMAGE_LAYOUT_UNDEFINED, // initialLayout
1589 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL // finalLayout
1590 );
1591 const auto attachmentId =
1592 (usedResolveAttachment ? static_cast<uint32_t>(attachments.size()) : VK_ATTACHMENT_UNUSED);
1593 const AttRef attachmentRef(
1594 // sType
1595 DE_NULL, // pNext
1596 attachmentId, // attachment
1597 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // layout
1598 0u // aspectMask
1599 );
1600 resolveAttachmentRefs.push_back(attachmentRef);
1601 attachments.push_back(singlesampleAttachment);
1602 }
1603 }
1604
1605 DE_ASSERT(colorAttachmentRefs.size() == resolveAttachmentRefs.size());
1606 DE_ASSERT(attachments.size() == colorAttachmentRefs.size() + resolveAttachmentRefs.size());
1607
1608 const SubpassDesc subpass(
1609 // sType
1610 DE_NULL, // pNext
1611 (VkSubpassDescriptionFlags)0, // flags
1612 VK_PIPELINE_BIND_POINT_GRAPHICS, // pipelineBindPoint
1613 0u, // viewMask
1614 0u, // inputAttachmentCount
1615 DE_NULL, // pInputAttachments
1616 (uint32_t)colorAttachmentRefs.size(), // colorAttachmentCount
1617 &colorAttachmentRefs[0], // pColorAttachments
1618 &resolveAttachmentRefs[0], // pResolveAttachments
1619 DE_NULL, // pDepthStencilAttachment
1620 0u, // preserveAttachmentCount
1621 DE_NULL // pPreserveAttachments
1622 );
1623 const RenderPassCreateInfo renderPassCreator(
1624 // sType
1625 DE_NULL, // pNext
1626 (VkRenderPassCreateFlags)0u, // flags
1627 (uint32_t)attachments.size(), // attachmentCount
1628 &attachments[0], // pAttachments
1629 1u, // subpassCount
1630 &subpass, // pSubpasses
1631 0u, // dependencyCount
1632 DE_NULL, // pDependencies
1633 0u, // correlatedViewMaskCount
1634 DE_NULL // pCorrelatedViewMasks
1635 );
1636
1637 return renderPassCreator.createRenderPass(vkd, device);
1638 }
1639
createRenderPassSwitch(bool usedResolveAttachment)1640 Move<VkRenderPass> MultisampleRenderPassTestInstance::createRenderPassSwitch(bool usedResolveAttachment)
1641 {
1642 switch (m_groupParams->renderingType)
1643 {
1644 case RENDERING_TYPE_RENDERPASS_LEGACY:
1645 return createRenderPass<RenderPass1Trait>(usedResolveAttachment);
1646 case RENDERING_TYPE_RENDERPASS2:
1647 return createRenderPass<RenderPass2Trait>(usedResolveAttachment);
1648 case RENDERING_TYPE_DYNAMIC_RENDERING:
1649 return Move<VkRenderPass>();
1650 default:
1651 TCU_THROW(InternalError, "Impossible");
1652 }
1653 }
1654
createRenderPassCompatible(void)1655 Move<VkRenderPass> MultisampleRenderPassTestInstance::createRenderPassCompatible(void)
1656 {
1657 if (m_testCompatibility)
1658 {
1659 // The compatible render pass is always created with a used resolve attachment.
1660 return createRenderPassSwitch(true);
1661 }
1662 else
1663 {
1664 return {};
1665 }
1666 }
1667
createRenderPipelineLayout(void)1668 Move<VkPipelineLayout> MultisampleRenderPassTestInstance::createRenderPipelineLayout(void)
1669 {
1670 const DeviceInterface &vkd = m_context.getDeviceInterface();
1671 VkDevice device = m_context.getDevice();
1672
1673 const VkPushConstantRange pushConstant = {VK_SHADER_STAGE_FRAGMENT_BIT, 0u, 4u};
1674 const VkPipelineLayoutCreateInfo createInfo = {VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
1675 DE_NULL,
1676 (vk::VkPipelineLayoutCreateFlags)0,
1677
1678 0u,
1679 DE_NULL,
1680
1681 1u,
1682 &pushConstant};
1683
1684 return createPipelineLayout(vkd, device, &createInfo);
1685 }
1686
createRenderPipeline(void)1687 Move<VkPipeline> MultisampleRenderPassTestInstance::createRenderPipeline(void)
1688 {
1689 const DeviceInterface &vkd = m_context.getDeviceInterface();
1690 VkDevice device = m_context.getDevice();
1691 const vk::BinaryCollection &binaryCollection = m_context.getBinaryCollection();
1692 const Unique<VkShaderModule> vertexShaderModule(
1693 createShaderModule(vkd, device, binaryCollection.get("quad-vert"), 0u));
1694 const Unique<VkShaderModule> fragmentShaderModule(
1695 createShaderModule(vkd, device, binaryCollection.get("quad-frag"), 0u));
1696 const Move<VkShaderModule> geometryShaderModule(
1697 m_layerCount == 1 ? Move<VkShaderModule>() : createShaderModule(vkd, device, binaryCollection.get("geom"), 0u));
1698 // Disable blending
1699 const VkPipelineColorBlendAttachmentState attachmentBlendState{
1700 VK_FALSE,
1701 VK_BLEND_FACTOR_SRC_ALPHA,
1702 VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
1703 VK_BLEND_OP_ADD,
1704 VK_BLEND_FACTOR_ONE,
1705 VK_BLEND_FACTOR_ONE,
1706 VK_BLEND_OP_ADD,
1707 VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT};
1708 std::vector<VkPipelineColorBlendAttachmentState> attachmentBlendStates(m_attachmentsCount, attachmentBlendState);
1709 const VkPipelineVertexInputStateCreateInfo vertexInputState = {
1710 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
1711 DE_NULL,
1712 (VkPipelineVertexInputStateCreateFlags)0u,
1713
1714 0u,
1715 DE_NULL,
1716
1717 0u,
1718 DE_NULL};
1719 const tcu::UVec2 renderArea(m_width, m_height);
1720 const std::vector<VkViewport> viewports(1, makeViewport(renderArea));
1721 const std::vector<VkRect2D> scissors(1, makeRect2D(renderArea));
1722
1723 const VkPipelineMultisampleStateCreateInfo multisampleState = {
1724 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
1725 DE_NULL,
1726 (VkPipelineMultisampleStateCreateFlags)0u,
1727
1728 sampleCountBitFromSampleCount(m_sampleCount),
1729 VK_FALSE,
1730 0.0f,
1731 DE_NULL,
1732 VK_FALSE,
1733 VK_FALSE,
1734 };
1735 const VkPipelineDepthStencilStateCreateInfo depthStencilState = {
1736 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
1737 DE_NULL,
1738 (VkPipelineDepthStencilStateCreateFlags)0u,
1739
1740 VK_FALSE,
1741 VK_TRUE,
1742 VK_COMPARE_OP_ALWAYS,
1743 VK_FALSE,
1744 VK_TRUE,
1745 {VK_STENCIL_OP_KEEP, VK_STENCIL_OP_INCREMENT_AND_WRAP, VK_STENCIL_OP_KEEP, VK_COMPARE_OP_ALWAYS, ~0u, ~0u,
1746 0xFFu / (m_sampleCount + 1)},
1747 {VK_STENCIL_OP_KEEP, VK_STENCIL_OP_INCREMENT_AND_WRAP, VK_STENCIL_OP_KEEP, VK_COMPARE_OP_ALWAYS, ~0u, ~0u,
1748 0xFFu / (m_sampleCount + 1)},
1749
1750 0.0f,
1751 1.0f};
1752 const VkPipelineColorBlendStateCreateInfo blendState = {VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
1753 DE_NULL,
1754 (VkPipelineColorBlendStateCreateFlags)0u,
1755
1756 VK_FALSE,
1757 VK_LOGIC_OP_COPY,
1758 uint32_t(attachmentBlendStates.size()),
1759 &attachmentBlendStates[0],
1760 {0.0f, 0.0f, 0.0f, 0.0f}};
1761
1762 void *pNext = DE_NULL;
1763
1764 #ifndef CTS_USES_VULKANSC
1765 std::vector<VkFormat> attachmentFormats(m_attachmentsCount, m_format);
1766 VkPipelineRenderingCreateInfoKHR renderingCreateInfo{VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
1767 DE_NULL,
1768 0u,
1769 m_attachmentsCount,
1770 attachmentFormats.data(),
1771 VK_FORMAT_UNDEFINED,
1772 VK_FORMAT_UNDEFINED};
1773 if (m_groupParams->renderingType == RENDERING_TYPE_DYNAMIC_RENDERING)
1774 pNext = &renderingCreateInfo;
1775 #endif // CTS_USES_VULKANSC
1776
1777 return makeGraphicsPipeline(
1778 vkd, // const DeviceInterface& vk
1779 device, // const VkDevice device
1780 *m_renderPipelineLayout, // const VkPipelineLayout pipelineLayout
1781 *vertexShaderModule, // const VkShaderModule vertexShaderModule
1782 DE_NULL, // const VkShaderModule tessellationControlShaderModule
1783 DE_NULL, // const VkShaderModule tessellationEvalShaderModule
1784 m_layerCount != 1 ? *geometryShaderModule :
1785 DE_NULL, // const VkShaderModule geometryShaderModule
1786 *fragmentShaderModule, // const VkShaderModule fragmentShaderModule
1787 *m_renderPass, // const VkRenderPass renderPass
1788 viewports, // const std::vector<VkViewport>& viewports
1789 scissors, // const std::vector<VkRect2D>& scissors
1790 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // const VkPrimitiveTopology topology
1791 0u, // const uint32_t subpass
1792 0u, // const uint32_t patchControlPoints
1793 &vertexInputState, // const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo
1794 DE_NULL, // const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
1795 &multisampleState, // const VkPipelineMultisampleStateCreateInfo* multisampleStateCreateInfo
1796 &depthStencilState, // const VkPipelineDepthStencilStateCreateInfo* depthStencilStateCreateInfo
1797 &blendState, // const VkPipelineColorBlendStateCreateInfo* colorBlendStateCreateInfo
1798 DE_NULL, // const VkPipelineDynamicStateCreateInfo* dynamicStateCreateInfo
1799 pNext); // const void* pNext
1800 }
1801
1802 #ifndef CTS_USES_VULKANSC
beginSecondaryCmdBuffer(VkCommandBuffer cmdBuffer) const1803 void MultisampleRenderPassTestInstance::beginSecondaryCmdBuffer(VkCommandBuffer cmdBuffer) const
1804 {
1805 const DeviceInterface &vkd = m_context.getDeviceInterface();
1806 std::vector<VkFormat> formats(m_attachmentsCount, m_format);
1807
1808 VkCommandBufferInheritanceRenderingInfoKHR inheritanceRenderingInfo{
1809 VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR, // VkStructureType sType;
1810 DE_NULL, // const void* pNext;
1811 0u, // VkRenderingFlagsKHR flags;
1812 0u, // uint32_t viewMask;
1813 m_attachmentsCount, // uint32_t colorAttachmentCount;
1814 formats.data(), // const VkFormat* pColorAttachmentFormats;
1815 VK_FORMAT_UNDEFINED, // VkFormat depthAttachmentFormat;
1816 VK_FORMAT_UNDEFINED, // VkFormat stencilAttachmentFormat;
1817 m_sampleCount, // VkSampleCountFlagBits rasterizationSamples;
1818 };
1819
1820 const VkCommandBufferInheritanceInfo bufferInheritanceInfo = initVulkanStructure(&inheritanceRenderingInfo);
1821 VkCommandBufferUsageFlags usageFlags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
1822 if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
1823 usageFlags |= VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
1824
1825 const VkCommandBufferBeginInfo commandBufBeginParams{
1826 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
1827 DE_NULL, // const void* pNext;
1828 usageFlags, // VkCommandBufferUsageFlags flags;
1829 &bufferInheritanceInfo};
1830
1831 VK_CHECK(vkd.beginCommandBuffer(cmdBuffer, &commandBufBeginParams));
1832 }
1833 #endif // CTS_USES_VULKANSC
1834
1835 class MaxAttachmenstsRenderPassTestInstance : public MultisampleRenderPassTestBase
1836 {
1837 public:
1838 MaxAttachmenstsRenderPassTestInstance(Context &context, TestConfig config);
1839 ~MaxAttachmenstsRenderPassTestInstance(void) = default;
1840
1841 tcu::TestStatus iterate(void);
1842
1843 private:
1844 template <typename RenderpassSubpass>
1845 void submit(void);
1846 void submitDynamicRendering(void);
1847
1848 #ifndef CTS_USES_VULKANSC
1849 void preRenderCommands(const DeviceInterface &vk, VkCommandBuffer cmdBuffer);
1850 void inbetweenRenderCommands(const DeviceInterface &vk, VkCommandBuffer cmdBuffer);
1851 #endif // CTS_USES_VULKANSC
1852 void drawFirstSubpass(const DeviceInterface &vk, VkCommandBuffer cmdBuffer);
1853 void drawSecondSubpass(const DeviceInterface &vk, VkCommandBuffer cmdBuffer);
1854 void postRenderCommands(const DeviceInterface &vk, VkCommandBuffer cmdBuffer);
1855
1856 void submitSwitch(RenderingType renderingType);
1857 void verify(void);
1858
1859 Move<VkDescriptorSetLayout> createDescriptorSetLayout(void);
1860 Move<VkDescriptorPool> createDescriptorPool(void);
1861 Move<VkDescriptorSet> createDescriptorSet(void);
1862
1863 template <typename RenderPassTrait>
1864 Move<VkRenderPass> createRenderPass(void);
1865 Move<VkRenderPass> createRenderPassSwitch(const RenderingType renderingType);
1866 void createRenderPipeline(GraphicsPipelineWrapper &graphicsPipeline, bool secondSubpass);
1867
1868 private:
1869 const std::vector<VkImageSp> m_multisampleImages;
1870 const std::vector<AllocationSp> m_multisampleImageMemory;
1871 const std::vector<VkImageViewSp> m_multisampleImageViews;
1872
1873 const std::vector<VkImageSp> m_singlesampleImages;
1874 const std::vector<AllocationSp> m_singlesampleImageMemory;
1875 const std::vector<VkImageViewSp> m_singlesampleImageViews;
1876
1877 const Unique<VkDescriptorSetLayout> m_descriptorSetLayout;
1878 const Unique<VkDescriptorPool> m_descriptorPool;
1879 const Unique<VkDescriptorSet> m_descriptorSet;
1880
1881 const Unique<VkRenderPass> m_renderPass;
1882 const Unique<VkFramebuffer> m_framebuffer;
1883
1884 PipelineLayoutWrapper m_pipelineLayoutPass0;
1885 GraphicsPipelineWrapper m_pipelinePass0;
1886 PipelineLayoutWrapper m_pipelineLayoutPass1;
1887 GraphicsPipelineWrapper m_pipelinePass1;
1888
1889 const std::vector<VkBufferSp> m_buffers;
1890 const std::vector<AllocationSp> m_bufferMemory;
1891
1892 const Unique<VkCommandPool> m_commandPool;
1893 tcu::ResultCollector m_resultCollector;
1894 };
1895
MaxAttachmenstsRenderPassTestInstance(Context & context,TestConfig config)1896 MaxAttachmenstsRenderPassTestInstance::MaxAttachmenstsRenderPassTestInstance(Context &context, TestConfig config)
1897 : MultisampleRenderPassTestBase(context, config)
1898
1899 , m_multisampleImages(createImages(m_sampleCount, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT))
1900 , m_multisampleImageMemory(createImageMemory(m_multisampleImages))
1901 , m_multisampleImageViews(createImageViews(m_multisampleImages))
1902
1903 , m_singlesampleImages(createImages(VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
1904 VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT |
1905 VK_IMAGE_USAGE_TRANSFER_SRC_BIT))
1906 , m_singlesampleImageMemory(createImageMemory(m_singlesampleImages))
1907 , m_singlesampleImageViews(createImageViews(m_singlesampleImages, m_baseLayer))
1908
1909 , m_descriptorSetLayout(createDescriptorSetLayout())
1910 , m_descriptorPool(createDescriptorPool())
1911 , m_descriptorSet(createDescriptorSet())
1912
1913 , m_renderPass(createRenderPassSwitch(config.groupParams->renderingType))
1914 , m_framebuffer(createFramebuffer(m_multisampleImageViews, m_singlesampleImageViews, *m_renderPass))
1915
1916 , m_pipelineLayoutPass0(config.groupParams->pipelineConstructionType, context.getDeviceInterface(),
1917 context.getDevice())
1918 , m_pipelinePass0(context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(),
1919 context.getDevice(), context.getDeviceExtensions(), m_groupParams->pipelineConstructionType)
1920 , m_pipelineLayoutPass1(config.groupParams->pipelineConstructionType, context.getDeviceInterface(),
1921 context.getDevice(), *m_descriptorSetLayout)
1922 , m_pipelinePass1(context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(),
1923 context.getDevice(), context.getDeviceExtensions(), m_groupParams->pipelineConstructionType)
1924
1925 , m_buffers(createBuffers())
1926 , m_bufferMemory(createBufferMemory(m_buffers))
1927
1928 , m_commandPool(createCommandPool(context.getDeviceInterface(), context.getDevice(),
1929 VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, context.getUniversalQueueFamilyIndex()))
1930 {
1931 createRenderPipeline(m_pipelinePass0, 0);
1932 createRenderPipeline(m_pipelinePass1, 1);
1933 }
1934
1935 template <typename RenderpassSubpass>
submit(void)1936 void MaxAttachmenstsRenderPassTestInstance::submit(void)
1937 {
1938 const DeviceInterface &vkd(m_context.getDeviceInterface());
1939 const VkDevice device(m_context.getDevice());
1940 const Unique<VkCommandBuffer> commandBuffer(
1941 allocateCommandBuffer(vkd, device, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1942 const typename RenderpassSubpass::SubpassBeginInfo subpassBeginInfo(DE_NULL, VK_SUBPASS_CONTENTS_INLINE);
1943 const typename RenderpassSubpass::SubpassEndInfo subpassEndInfo(DE_NULL);
1944
1945 beginCommandBuffer(vkd, *commandBuffer);
1946
1947 // Memory barriers between previous copies and rendering
1948 {
1949 std::vector<VkImageMemoryBarrier> barriers;
1950
1951 for (size_t dstNdx = 0; dstNdx < m_singlesampleImages.size(); dstNdx++)
1952 {
1953 const VkImageMemoryBarrier barrier = {VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
1954 DE_NULL,
1955
1956 VK_ACCESS_TRANSFER_READ_BIT,
1957 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
1958
1959 VK_IMAGE_LAYOUT_UNDEFINED,
1960 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
1961
1962 VK_QUEUE_FAMILY_IGNORED,
1963 VK_QUEUE_FAMILY_IGNORED,
1964
1965 **m_singlesampleImages[dstNdx],
1966 {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, m_baseLayer, m_layerCount}};
1967
1968 barriers.push_back(barrier);
1969 }
1970
1971 vkd.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
1972 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL,
1973 (uint32_t)barriers.size(), &barriers[0]);
1974 }
1975
1976 {
1977 const VkRenderPassBeginInfo beginInfo = {VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
1978 DE_NULL,
1979
1980 *m_renderPass,
1981 *m_framebuffer,
1982
1983 {{0u, 0u}, {m_width, m_height}},
1984
1985 0u,
1986 DE_NULL};
1987 RenderpassSubpass::cmdBeginRenderPass(vkd, *commandBuffer, &beginInfo, &subpassBeginInfo);
1988 }
1989
1990 // Clear everything to black
1991 clearAttachments(*commandBuffer);
1992
1993 // First subpass - render black samples
1994 drawFirstSubpass(vkd, *commandBuffer);
1995
1996 // Second subpasss - merge attachments
1997 RenderpassSubpass::cmdNextSubpass(vkd, *commandBuffer, &subpassBeginInfo, &subpassEndInfo);
1998 drawSecondSubpass(vkd, *commandBuffer);
1999
2000 RenderpassSubpass::cmdEndRenderPass(vkd, *commandBuffer, &subpassEndInfo);
2001
2002 postRenderCommands(vkd, *commandBuffer);
2003
2004 endCommandBuffer(vkd, *commandBuffer);
2005
2006 submitCommandsAndWait(vkd, device, m_context.getUniversalQueue(), *commandBuffer);
2007
2008 for (size_t memoryBufferNdx = 0; memoryBufferNdx < m_bufferMemory.size(); memoryBufferNdx++)
2009 invalidateMappedMemoryRange(vkd, device, m_bufferMemory[memoryBufferNdx]->getMemory(), 0u, VK_WHOLE_SIZE);
2010 }
2011
submitDynamicRendering()2012 void MaxAttachmenstsRenderPassTestInstance::submitDynamicRendering()
2013 {
2014 #ifndef CTS_USES_VULKANSC
2015 const DeviceInterface &vk(m_context.getDeviceInterface());
2016 const VkDevice device(m_context.getDevice());
2017 const Unique<VkCommandBuffer> cmdBuffer(
2018 allocateCommandBuffer(vk, device, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
2019 Move<VkCommandBuffer> secCmdBuffers[2];
2020
2021 const tcu::TextureFormat format(mapVkFormat(m_format));
2022 const tcu::TextureChannelClass channelClass = tcu::getTextureChannelClass(format.type);
2023 const bool isIntClass = (channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER) ||
2024 (channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER);
2025 VkResolveModeFlagBits resolveMode = isIntClass ? VK_RESOLVE_MODE_SAMPLE_ZERO_BIT : VK_RESOLVE_MODE_AVERAGE_BIT;
2026
2027 std::vector<VkRenderingAttachmentInfo> firstColorAttachments(
2028 m_multisampleImages.size(),
2029 {
2030 VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO, // VkStructureType sType;
2031 DE_NULL, // const void* pNext;
2032 VK_NULL_HANDLE, // VkImageView imageView;
2033 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout imageLayout;
2034 resolveMode, // VkResolveModeFlagBits resolveMode;
2035 VK_NULL_HANDLE, // VkImageView resolveImageView;
2036 m_inputImageReadLayout, // VkImageLayout resolveImageLayout;
2037 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
2038 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
2039 getClearValue() // VkClearValue clearValue;
2040 });
2041 std::vector<VkRenderingAttachmentInfo> secondColorAttachments(m_multisampleImages.size(), firstColorAttachments[0]);
2042 for (size_t i = 0; i < m_multisampleImages.size(); ++i)
2043 {
2044 firstColorAttachments[i].imageView = **m_multisampleImageViews[i];
2045 firstColorAttachments[i].resolveImageView = **m_singlesampleImageViews[i];
2046
2047 secondColorAttachments[i].imageView = **m_singlesampleImageViews[i];
2048 secondColorAttachments[i].imageLayout = m_inputImageReadLayout;
2049 secondColorAttachments[i].resolveMode = VK_RESOLVE_MODE_NONE;
2050 secondColorAttachments[i].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
2051 }
2052
2053 VkRenderingInfo firstRenderingInfo{
2054 VK_STRUCTURE_TYPE_RENDERING_INFO,
2055 DE_NULL,
2056 0, // VkRenderingFlagsKHR flags;
2057 makeRect2D(m_width, m_height), // VkRect2D renderArea;
2058 1u, // uint32_t layerCount;
2059 0u, // uint32_t viewMask;
2060 (uint32_t)firstColorAttachments.size(), // uint32_t colorAttachmentCount;
2061 firstColorAttachments.data(), // const VkRenderingAttachmentInfoKHR* pColorAttachments;
2062 DE_NULL, // const VkRenderingAttachmentInfoKHR* pDepthAttachment;
2063 DE_NULL, // const VkRenderingAttachmentInfoKHR* pStencilAttachment;
2064 };
2065 VkRenderingInfo secondRenderingInfo = firstRenderingInfo;
2066 secondRenderingInfo.pColorAttachments = secondColorAttachments.data();
2067
2068 std::vector<uint32_t> colorAttachmentLocationsAndInputs(firstColorAttachments.size());
2069 std::iota(colorAttachmentLocationsAndInputs.begin(), colorAttachmentLocationsAndInputs.end(), 0);
2070
2071 VkRenderingAttachmentLocationInfoKHR renderingAttachmentLocationInfo = initVulkanStructure();
2072 renderingAttachmentLocationInfo.colorAttachmentCount = (uint32_t)colorAttachmentLocationsAndInputs.size();
2073 renderingAttachmentLocationInfo.pColorAttachmentLocations = colorAttachmentLocationsAndInputs.data();
2074
2075 VkRenderingInputAttachmentIndexInfoKHR renderingInputAttachmentIndexInfo = initVulkanStructure();
2076 renderingInputAttachmentIndexInfo.colorAttachmentCount = (uint32_t)colorAttachmentLocationsAndInputs.size();
2077 renderingInputAttachmentIndexInfo.pColorAttachmentInputIndices = colorAttachmentLocationsAndInputs.data();
2078
2079 if (m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
2080 {
2081 secCmdBuffers[0] = allocateCommandBuffer(vk, device, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
2082 secCmdBuffers[1] = allocateCommandBuffer(vk, device, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
2083
2084 // record secondary command buffer for first subpass
2085 beginSecondaryCmdBuffer(vk, *secCmdBuffers[0], (uint32_t)m_multisampleImages.size(), m_sampleCount);
2086 vk.cmdBeginRendering(*secCmdBuffers[0], &firstRenderingInfo);
2087 drawFirstSubpass(vk, *secCmdBuffers[0]);
2088 vk.cmdEndRendering(*secCmdBuffers[0]);
2089 endCommandBuffer(vk, *secCmdBuffers[0]);
2090
2091 // record secondary command buffer for second subpass
2092 beginSecondaryCmdBuffer(vk, *secCmdBuffers[1], (uint32_t)m_multisampleImages.size(), VK_SAMPLE_COUNT_1_BIT);
2093 vk.cmdBeginRendering(*secCmdBuffers[1], &secondRenderingInfo);
2094 vk.cmdSetRenderingAttachmentLocationsKHR(*secCmdBuffers[1], &renderingAttachmentLocationInfo);
2095 vk.cmdSetRenderingInputAttachmentIndicesKHR(*secCmdBuffers[1], &renderingInputAttachmentIndexInfo);
2096 drawSecondSubpass(vk, *secCmdBuffers[1]);
2097 vk.cmdEndRendering(*secCmdBuffers[1]);
2098 endCommandBuffer(vk, *secCmdBuffers[1]);
2099
2100 renderingInputAttachmentIndexInfo.pNext = DE_NULL;
2101
2102 // record primary command buffer
2103 beginCommandBuffer(vk, *cmdBuffer);
2104 preRenderCommands(vk, *cmdBuffer);
2105 vk.cmdExecuteCommands(*cmdBuffer, 1u, &*secCmdBuffers[0]);
2106 inbetweenRenderCommands(vk, *cmdBuffer);
2107 vk.cmdExecuteCommands(*cmdBuffer, 1u, &*secCmdBuffers[1]);
2108 postRenderCommands(vk, *cmdBuffer);
2109 endCommandBuffer(vk, *cmdBuffer);
2110 }
2111 else
2112 {
2113 beginCommandBuffer(vk, *cmdBuffer);
2114
2115 preRenderCommands(vk, *cmdBuffer);
2116
2117 // First dynamic render pass - render black samples
2118 vk.cmdBeginRendering(*cmdBuffer, &firstRenderingInfo);
2119 drawFirstSubpass(vk, *cmdBuffer);
2120 vk.cmdEndRendering(*cmdBuffer);
2121
2122 inbetweenRenderCommands(vk, *cmdBuffer);
2123
2124 // Second dynamic render pass - merge resolved attachments
2125 vk.cmdBeginRendering(*cmdBuffer, &secondRenderingInfo);
2126 vk.cmdSetRenderingAttachmentLocationsKHR(*cmdBuffer, &renderingAttachmentLocationInfo);
2127 vk.cmdSetRenderingInputAttachmentIndicesKHR(*cmdBuffer, &renderingInputAttachmentIndexInfo);
2128 drawSecondSubpass(vk, *cmdBuffer);
2129 vk.cmdEndRendering(*cmdBuffer);
2130
2131 postRenderCommands(vk, *cmdBuffer);
2132 endCommandBuffer(vk, *cmdBuffer);
2133 }
2134
2135 submitCommandsAndWait(vk, device, m_context.getUniversalQueue(), *cmdBuffer);
2136
2137 for (size_t memoryBufferNdx = 0; memoryBufferNdx < m_bufferMemory.size(); memoryBufferNdx++)
2138 invalidateMappedMemoryRange(vk, device, m_bufferMemory[memoryBufferNdx]->getMemory(), 0u, VK_WHOLE_SIZE);
2139 #endif
2140 }
2141
2142 #ifndef CTS_USES_VULKANSC
preRenderCommands(const DeviceInterface & vk,VkCommandBuffer cmdBuffer)2143 void MaxAttachmenstsRenderPassTestInstance::preRenderCommands(const DeviceInterface &vk, VkCommandBuffer cmdBuffer)
2144 {
2145 const VkImageSubresourceRange subresourceRange{VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, m_layerCount};
2146 std::vector<VkImageMemoryBarrier> barriers(
2147 m_multisampleImages.size() + m_singlesampleImages.size(),
2148 makeImageMemoryBarrier(VK_ACCESS_TRANSFER_READ_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
2149 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 0,
2150 subresourceRange));
2151
2152 for (size_t i = 0; i < m_multisampleImages.size(); ++i)
2153 barriers[i].image = **m_multisampleImages[i];
2154 for (size_t i = m_multisampleImages.size(); i < barriers.size(); ++i)
2155 {
2156 barriers[i].image = **m_singlesampleImages[i - m_multisampleImages.size()];
2157 barriers[i].newLayout = m_inputImageReadLayout;
2158 }
2159
2160 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u,
2161 0u, DE_NULL, 0u, DE_NULL, (uint32_t)barriers.size(), barriers.data());
2162 }
2163
inbetweenRenderCommands(const DeviceInterface & vk,VkCommandBuffer cmdBuffer)2164 void MaxAttachmenstsRenderPassTestInstance::inbetweenRenderCommands(const DeviceInterface &vk,
2165 VkCommandBuffer cmdBuffer)
2166 {
2167 VkMemoryBarrier memoryBarrier =
2168 makeMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT);
2169 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
2170 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 1u, &memoryBarrier, 0u,
2171 DE_NULL, 0, DE_NULL);
2172 }
2173 #endif // CTS_USES_VULKANSC
2174
drawFirstSubpass(const DeviceInterface & vk,VkCommandBuffer cmdBuffer)2175 void MaxAttachmenstsRenderPassTestInstance::drawFirstSubpass(const DeviceInterface &vk, VkCommandBuffer cmdBuffer)
2176 {
2177 vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipelinePass0.getPipeline());
2178 vk.cmdDraw(cmdBuffer, 6u, 1u, 0u, 0u);
2179 }
2180
drawSecondSubpass(const DeviceInterface & vk,VkCommandBuffer cmdBuffer)2181 void MaxAttachmenstsRenderPassTestInstance::drawSecondSubpass(const DeviceInterface &vk, VkCommandBuffer cmdBuffer)
2182 {
2183 vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipelinePass1.getPipeline());
2184 vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayoutPass1, 0, 1u,
2185 &*m_descriptorSet, 0, NULL);
2186 vk.cmdDraw(cmdBuffer, 6u, 1u, 0u, 0u);
2187 }
2188
postRenderCommands(const DeviceInterface & vk,VkCommandBuffer cmdBuffer)2189 void MaxAttachmenstsRenderPassTestInstance::postRenderCommands(const DeviceInterface &vk, VkCommandBuffer cmdBuffer)
2190 {
2191 const VkImageSubresourceRange subresourceRange{VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, m_layerCount};
2192
2193 // Memory barriers between rendering and copies
2194 std::vector<VkImageMemoryBarrier> imageBarriers(
2195 m_singlesampleImages.size(),
2196 makeImageMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
2197 m_inputImageReadLayout, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 0u, subresourceRange));
2198
2199 for (size_t dstNdx = 0; dstNdx < m_singlesampleImages.size(); dstNdx++)
2200 imageBarriers[dstNdx].image = **m_singlesampleImages[dstNdx];
2201
2202 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
2203 0u, DE_NULL, 0u, DE_NULL, (uint32_t)imageBarriers.size(), imageBarriers.data());
2204
2205 // Copy image memory to buffers
2206 const VkBufferImageCopy region =
2207 makeBufferImageCopy({m_width, m_height, 1u}, {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, m_layerCount});
2208 for (size_t dstNdx = 0; dstNdx < m_singlesampleImages.size(); dstNdx++)
2209 vk.cmdCopyImageToBuffer(cmdBuffer, **m_singlesampleImages[dstNdx], VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
2210 **m_buffers[dstNdx], 1u, ®ion);
2211
2212 // Memory barriers between copies and host access
2213 std::vector<VkBufferMemoryBarrier> bufferBarriers(
2214 m_buffers.size(),
2215 makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, 0u, 0u, VK_WHOLE_SIZE));
2216 for (size_t i = 0u; i < bufferBarriers.size(); ++i)
2217 bufferBarriers[i].buffer = **m_buffers[i];
2218
2219 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL,
2220 (uint32_t)bufferBarriers.size(), bufferBarriers.data(), 0u, DE_NULL);
2221 }
2222
submitSwitch(RenderingType renderingType)2223 void MaxAttachmenstsRenderPassTestInstance::submitSwitch(RenderingType renderingType)
2224 {
2225 switch (renderingType)
2226 {
2227 case RENDERING_TYPE_RENDERPASS_LEGACY:
2228 submit<RenderpassSubpass1>();
2229 break;
2230 case RENDERING_TYPE_RENDERPASS2:
2231 submit<RenderpassSubpass2>();
2232 break;
2233 case RENDERING_TYPE_DYNAMIC_RENDERING:
2234 submitDynamicRendering();
2235 break;
2236 default:
2237 TCU_THROW(InternalError, "Impossible");
2238 }
2239 }
2240
2241 template <typename VecType>
isValueAboveThreshold1(const VecType & vale,const VecType & threshold)2242 bool isValueAboveThreshold1(const VecType &vale, const VecType &threshold)
2243 {
2244 return (vale[0] > threshold[0]);
2245 }
2246
2247 template <typename VecType>
isValueAboveThreshold2(const VecType & vale,const VecType & threshold)2248 bool isValueAboveThreshold2(const VecType &vale, const VecType &threshold)
2249 {
2250 return (vale[0] > threshold[0]) || (vale[1] > threshold[1]);
2251 }
2252
2253 template <typename VecType>
isValueAboveThreshold3(const VecType & vale,const VecType & threshold)2254 bool isValueAboveThreshold3(const VecType &vale, const VecType &threshold)
2255 {
2256 return (vale[0] > threshold[0]) || (vale[1] > threshold[1]) || (vale[2] > threshold[2]);
2257 }
2258
2259 template <typename VecType>
isValueAboveThreshold4(const VecType & vale,const VecType & threshold)2260 bool isValueAboveThreshold4(const VecType &vale, const VecType &threshold)
2261 {
2262 return (vale[0] > threshold[0]) || (vale[1] > threshold[1]) || (vale[2] > threshold[2]) || (vale[3] > threshold[3]);
2263 }
2264
verify(void)2265 void MaxAttachmenstsRenderPassTestInstance::verify(void)
2266 {
2267 const Vec4 errorColor(1.0f, 0.0f, 0.0f, 1.0f);
2268 const Vec4 okColor(0.0f, 1.0f, 0.0f, 1.0f);
2269 const tcu::TextureFormat format(mapVkFormat(m_format));
2270 const tcu::TextureChannelClass channelClass(tcu::getTextureChannelClass(format.type));
2271 const int componentCount(tcu::getNumUsedChannels(format.order));
2272 const int outputsCount = m_attachmentsCount / 2;
2273
2274 DE_ASSERT((componentCount >= 0) && (componentCount < 5));
2275
2276 std::vector<tcu::ConstPixelBufferAccess> accesses;
2277 for (int outputNdx = 0; outputNdx < outputsCount; ++outputNdx)
2278 {
2279 void *const ptr = m_bufferMemory[outputNdx]->getHostPtr();
2280 accesses.push_back(tcu::ConstPixelBufferAccess(format, m_width, m_height, 1, ptr));
2281 }
2282
2283 tcu::TextureLevel errorMask(tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), m_width,
2284 m_height, outputsCount);
2285 tcu::TestLog &log(m_context.getTestContext().getLog());
2286 bool isOk = true;
2287
2288 switch (channelClass)
2289 {
2290 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
2291 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
2292 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
2293 {
2294 const Vec4 refColor(0.0f, 0.3f, 0.6f, 0.75f);
2295 const Vec4 threshold(getFormatThreshold());
2296
2297 typedef bool (*ValueAboveThresholdFn)(const Vec4 &, const Vec4 &);
2298 ValueAboveThresholdFn componentToFnMap[4] = {isValueAboveThreshold1<Vec4>, isValueAboveThreshold2<Vec4>,
2299 isValueAboveThreshold3<Vec4>, isValueAboveThreshold4<Vec4>};
2300 ValueAboveThresholdFn isValueAboveThreshold = componentToFnMap[componentCount - 1];
2301 bool isSRGBFormat = tcu::isSRGB(format);
2302
2303 for (int outputNdx = 0; outputNdx < outputsCount; outputNdx++)
2304 for (int y = 0; y < (int)m_height; y++)
2305 for (int x = 0; x < (int)m_width; x++)
2306 {
2307 Vec4 color = accesses[outputNdx].getPixel(x, y);
2308 if (isSRGBFormat)
2309 color = tcu::sRGBToLinear(color);
2310
2311 const Vec4 diff(tcu::abs(color - refColor));
2312
2313 if (isValueAboveThreshold(diff, threshold))
2314 {
2315 isOk = false;
2316 errorMask.getAccess().setPixel(errorColor, x, y, outputNdx);
2317 break;
2318 }
2319 else
2320 errorMask.getAccess().setPixel(okColor, x, y, outputNdx);
2321 }
2322 break;
2323 }
2324
2325 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
2326 {
2327 const UVec4 refColor(0, 48, 144, 189);
2328 UVec4 threshold(1, 1, 1, 1);
2329
2330 if (m_format == VK_FORMAT_A2B10G10R10_UINT_PACK32)
2331 threshold[3] = 200;
2332
2333 typedef bool (*ValueAboveThresholdFn)(const UVec4 &, const UVec4 &);
2334 ValueAboveThresholdFn componentToFnMap[4] = {isValueAboveThreshold1<UVec4>, isValueAboveThreshold2<UVec4>,
2335 isValueAboveThreshold3<UVec4>, isValueAboveThreshold4<UVec4>};
2336 ValueAboveThresholdFn isValueAboveThreshold = componentToFnMap[componentCount - 1];
2337
2338 for (int outputNdx = 0; outputNdx < outputsCount; outputNdx++)
2339 for (int y = 0; y < (int)m_height; y++)
2340 for (int x = 0; x < (int)m_width; x++)
2341 {
2342 const UVec4 color(accesses[outputNdx].getPixelUint(x, y));
2343 const UVec4 diff(
2344 std::abs(int(color.x()) - int(refColor.x())), std::abs(int(color.y()) - int(refColor.y())),
2345 std::abs(int(color.z()) - int(refColor.z())), std::abs(int(color.w()) - int(refColor.w())));
2346
2347 if (isValueAboveThreshold(diff, threshold))
2348 {
2349 isOk = false;
2350 errorMask.getAccess().setPixel(errorColor, x, y, outputNdx);
2351 break;
2352 }
2353 else
2354 errorMask.getAccess().setPixel(okColor, x, y, outputNdx);
2355 }
2356 break;
2357 }
2358
2359 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
2360 {
2361 const IVec4 refColor(0, 24, 75, 93);
2362 const IVec4 threshold(1, 1, 1, 1);
2363
2364 typedef bool (*ValueAboveThresholdFn)(const IVec4 &, const IVec4 &);
2365 ValueAboveThresholdFn componentToFnMap[4] = {isValueAboveThreshold1<IVec4>, isValueAboveThreshold2<IVec4>,
2366 isValueAboveThreshold3<IVec4>, isValueAboveThreshold4<IVec4>};
2367 ValueAboveThresholdFn isValueAboveThreshold = componentToFnMap[componentCount - 1];
2368
2369 for (int outputNdx = 0; outputNdx < outputsCount; outputNdx++)
2370 for (int y = 0; y < (int)m_height; y++)
2371 for (int x = 0; x < (int)m_width; x++)
2372 {
2373 const IVec4 color(accesses[outputNdx].getPixelInt(x, y));
2374 const IVec4 diff(std::abs(color.x() - refColor.x()), std::abs(color.y() - refColor.y()),
2375 std::abs(color.z() - refColor.z()), std::abs(color.w() - 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 default:
2390 DE_FATAL("Unknown channel class");
2391 }
2392
2393 if (!isOk)
2394 {
2395 const std::string sectionName("MaxAttachmentsVerify");
2396 const tcu::ScopedLogSection section(log, sectionName, sectionName);
2397
2398 logImage("ErrorMask", errorMask.getAccess());
2399 m_resultCollector.fail("Fail");
2400 }
2401 }
2402
iterate(void)2403 tcu::TestStatus MaxAttachmenstsRenderPassTestInstance::iterate(void)
2404 {
2405 submitSwitch(m_groupParams->renderingType);
2406 verify();
2407
2408 return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage());
2409 }
2410
createDescriptorSetLayout()2411 Move<VkDescriptorSetLayout> MaxAttachmenstsRenderPassTestInstance::createDescriptorSetLayout()
2412 {
2413 const VkDescriptorSetLayoutBinding bindingTemplate = {
2414 0, // binding
2415 VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, // descriptorType
2416 1u, // descriptorCount
2417 VK_SHADER_STAGE_FRAGMENT_BIT, // stageFlags
2418 DE_NULL // pImmutableSamplers
2419 };
2420
2421 std::vector<VkDescriptorSetLayoutBinding> bindings(m_attachmentsCount, bindingTemplate);
2422 for (uint32_t idx = 0; idx < m_attachmentsCount; ++idx)
2423 bindings[idx].binding = idx;
2424
2425 const VkDescriptorSetLayoutCreateInfo createInfo = {
2426 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // sType
2427 DE_NULL, // pNext
2428 0u, // flags
2429 m_attachmentsCount, // bindingCount
2430 &bindings[0] // pBindings
2431 };
2432
2433 return ::createDescriptorSetLayout(m_context.getDeviceInterface(), m_context.getDevice(), &createInfo);
2434 }
2435
createDescriptorPool()2436 Move<VkDescriptorPool> MaxAttachmenstsRenderPassTestInstance::createDescriptorPool()
2437 {
2438 const VkDescriptorPoolSize size = {
2439 VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, // type
2440 m_attachmentsCount // descriptorCount
2441 };
2442
2443 const VkDescriptorPoolCreateInfo createInfo = {
2444 VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, // sType
2445 DE_NULL, // pNext
2446 VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, // flags
2447 1u, // maxSets
2448 1u, // poolSizeCount
2449 &size // pPoolSizes
2450 };
2451
2452 return ::createDescriptorPool(m_context.getDeviceInterface(), m_context.getDevice(), &createInfo);
2453 }
2454
createDescriptorSet()2455 Move<VkDescriptorSet> MaxAttachmenstsRenderPassTestInstance::createDescriptorSet()
2456 {
2457 const VkDescriptorSetAllocateInfo allocateInfo = {
2458 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // sType
2459 DE_NULL, // pNext
2460 *m_descriptorPool, // descriptorPool
2461 1u, // descriptorSetCount
2462 &*m_descriptorSetLayout // pSetLayouts
2463 };
2464
2465 const vk::DeviceInterface &vkd = m_context.getDeviceInterface();
2466 vk::VkDevice device = m_context.getDevice();
2467 Move<VkDescriptorSet> descriptorSet = allocateDescriptorSet(vkd, device, &allocateInfo);
2468 vector<VkDescriptorImageInfo> descriptorImageInfo(m_attachmentsCount);
2469 vector<VkWriteDescriptorSet> descriptorWrites(m_attachmentsCount);
2470
2471 for (uint32_t idx = 0; idx < m_attachmentsCount; ++idx)
2472 {
2473 descriptorImageInfo[idx] = {
2474 DE_NULL, // VkSampler sampler
2475 **m_singlesampleImageViews[idx], // VkImageView imageView
2476 m_inputImageReadLayout // VkImageLayout imageLayout
2477 };
2478
2479 descriptorWrites[idx] = {
2480 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // VkStructureType sType
2481 DE_NULL, // const void* pNext
2482 *descriptorSet, // VkDescriptorSet dstSet
2483 (uint32_t)idx, // uint32_t dstBinding
2484 0u, // uint32_t dstArrayElement
2485 1u, // uint32_t descriptorCount
2486 VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, // VkDescriptorType descriptorType
2487 &descriptorImageInfo[idx], // const VkDescriptorImageInfo* pImageInfo
2488 DE_NULL, // const VkDescriptorBufferInfo* pBufferInfo
2489 DE_NULL // const VkBufferView* pTexelBufferView
2490 };
2491 }
2492
2493 vkd.updateDescriptorSets(device, (uint32_t)descriptorWrites.size(), &descriptorWrites[0], 0u, DE_NULL);
2494 return descriptorSet;
2495 }
2496
2497 template <typename RenderPassTrait>
createRenderPass(void)2498 Move<VkRenderPass> MaxAttachmenstsRenderPassTestInstance::createRenderPass(void)
2499 {
2500 // make name for RenderPass1Trait or RenderPass2Trait shorter
2501 typedef RenderPassTrait RPT;
2502
2503 typedef typename RPT::AttDesc AttDesc;
2504 typedef typename RPT::AttRef AttRef;
2505 typedef typename RPT::SubpassDep SubpassDep;
2506 typedef typename RPT::SubpassDesc SubpassDesc;
2507 typedef typename RPT::RenderPassCreateInfo RenderPassCreateInfo;
2508
2509 const DeviceInterface &vkd = m_context.getDeviceInterface();
2510 VkDevice device = m_context.getDevice();
2511 std::vector<AttDesc> attachments;
2512 std::vector<AttRef> sp0colorAttachmentRefs;
2513 std::vector<AttRef> sp0resolveAttachmentRefs;
2514 std::vector<AttRef> sp1inAttachmentRefs;
2515 std::vector<AttRef> sp1colorAttachmentRefs;
2516
2517 for (size_t attachmentNdx = 0; attachmentNdx < m_attachmentsCount; attachmentNdx++)
2518 {
2519 // define first subpass outputs
2520 {
2521 const AttDesc multisampleAttachment(DE_NULL, // pNext
2522 0u, // flags
2523 m_format, // format
2524 m_sampleCount, // samples
2525 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // loadOp
2526 VK_ATTACHMENT_STORE_OP_STORE, // storeOp
2527 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // stencilLoadOp
2528 VK_ATTACHMENT_STORE_OP_DONT_CARE, // stencilStoreOp
2529 VK_IMAGE_LAYOUT_UNDEFINED, // initialLayout
2530 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // finalLayout
2531 );
2532 const AttRef attachmentRef(DE_NULL,
2533 (uint32_t)attachments.size(), // attachment
2534 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // layout
2535 0u // aspectMask
2536 );
2537 sp0colorAttachmentRefs.push_back(attachmentRef);
2538 attachments.push_back(multisampleAttachment);
2539 }
2540 // define first subpass resolve attachments
2541 {
2542 const AttDesc singlesampleAttachment(DE_NULL, // pNext
2543 0u, // flags
2544 m_format, // format
2545 VK_SAMPLE_COUNT_1_BIT, // samples
2546 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // loadOp
2547 VK_ATTACHMENT_STORE_OP_STORE, // storeOp
2548 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // stencilLoadOp
2549 VK_ATTACHMENT_STORE_OP_DONT_CARE, // stencilStoreOp
2550 VK_IMAGE_LAYOUT_UNDEFINED, // initialLayout
2551 VK_IMAGE_LAYOUT_GENERAL // finalLayout
2552 );
2553 const AttRef attachmentRef(DE_NULL, // pNext
2554 (uint32_t)attachments.size(), // attachment
2555 VK_IMAGE_LAYOUT_GENERAL, // layout
2556 0u // aspectMask
2557 );
2558 sp0resolveAttachmentRefs.push_back(attachmentRef);
2559 attachments.push_back(singlesampleAttachment);
2560 }
2561 // define second subpass inputs
2562 {
2563 const AttRef attachmentRef(DE_NULL, // pNext
2564 (uint32_t)attachments.size() - 1, // attachment
2565 VK_IMAGE_LAYOUT_GENERAL, // layout
2566 VK_IMAGE_ASPECT_COLOR_BIT // aspectMask
2567 );
2568 sp1inAttachmentRefs.push_back(attachmentRef);
2569 }
2570 // define second subpass outputs - it merges pairs of
2571 // results that were produced by the first subpass
2572 if (attachmentNdx < (m_attachmentsCount / 2))
2573 {
2574 const AttRef colorAttachmentRef(DE_NULL, // pNext
2575 (uint32_t)attachments.size() - 1, // attachment
2576 VK_IMAGE_LAYOUT_GENERAL, // layout
2577 0u // aspectMask
2578 );
2579 sp1colorAttachmentRefs.push_back(colorAttachmentRef);
2580 }
2581 }
2582
2583 DE_ASSERT(sp0colorAttachmentRefs.size() == sp0resolveAttachmentRefs.size());
2584 DE_ASSERT(attachments.size() == sp0colorAttachmentRefs.size() + sp0resolveAttachmentRefs.size());
2585
2586 {
2587 const SubpassDesc subpass0(
2588 // sType
2589 DE_NULL, // pNext
2590 (VkSubpassDescriptionFlags)0, // flags
2591 VK_PIPELINE_BIND_POINT_GRAPHICS, // pipelineBindPoint
2592 0u, // viewMask
2593 0u, // inputAttachmentCount
2594 DE_NULL, // pInputAttachments
2595 (uint32_t)sp0colorAttachmentRefs.size(), // colorAttachmentCount
2596 &sp0colorAttachmentRefs[0], // pColorAttachments
2597 &sp0resolveAttachmentRefs[0], // pResolveAttachments
2598 DE_NULL, // pDepthStencilAttachment
2599 0u, // preserveAttachmentCount
2600 DE_NULL // pPreserveAttachments
2601 );
2602 const SubpassDesc subpass1(
2603 // sType
2604 DE_NULL, // pNext
2605 (VkSubpassDescriptionFlags)0, // flags
2606 VK_PIPELINE_BIND_POINT_GRAPHICS, // pipelineBindPoint
2607 0u, // viewMask
2608 (uint32_t)sp1inAttachmentRefs.size(), // inputAttachmentCount
2609 &sp1inAttachmentRefs[0], // pInputAttachments
2610 (uint32_t)sp1colorAttachmentRefs.size(), // colorAttachmentCount
2611 &sp1colorAttachmentRefs[0], // pColorAttachments
2612 DE_NULL, // pResolveAttachments
2613 DE_NULL, // pDepthStencilAttachment
2614 0u, // preserveAttachmentCount
2615 DE_NULL // pPreserveAttachments
2616 );
2617 SubpassDesc subpasses[] = {subpass0, subpass1};
2618 const SubpassDep subpassDependency(DE_NULL, // pNext
2619 0u, // srcSubpass
2620 1u, // dstSubpass
2621 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, // srcStageMask
2622 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, // dstStageMask
2623 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // srcAccessMask
2624 VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, // dstAccessMask
2625 0u, // dependencyFlags
2626 0u // viewOffset
2627 );
2628 const RenderPassCreateInfo renderPassCreator(
2629 // sType
2630 DE_NULL, // pNext
2631 (VkRenderPassCreateFlags)0u, // flags
2632 (uint32_t)attachments.size(), // attachmentCount
2633 &attachments[0], // pAttachments
2634 2u, // subpassCount
2635 subpasses, // pSubpasses
2636 1u, // dependencyCount
2637 &subpassDependency, // pDependencies
2638 0u, // correlatedViewMaskCount
2639 DE_NULL // pCorrelatedViewMasks
2640 );
2641
2642 return renderPassCreator.createRenderPass(vkd, device);
2643 }
2644 }
2645
createRenderPassSwitch(const RenderingType renderingType)2646 Move<VkRenderPass> MaxAttachmenstsRenderPassTestInstance::createRenderPassSwitch(const RenderingType renderingType)
2647 {
2648 switch (renderingType)
2649 {
2650 case RENDERING_TYPE_RENDERPASS_LEGACY:
2651 return createRenderPass<RenderPass1Trait>();
2652 case RENDERING_TYPE_RENDERPASS2:
2653 return createRenderPass<RenderPass2Trait>();
2654 case RENDERING_TYPE_DYNAMIC_RENDERING:
2655 return Move<VkRenderPass>();
2656 default:
2657 TCU_THROW(InternalError, "Impossible");
2658 }
2659 }
2660
createRenderPipeline(GraphicsPipelineWrapper & graphicsPipeline,bool secondSubpass)2661 void MaxAttachmenstsRenderPassTestInstance::createRenderPipeline(GraphicsPipelineWrapper &graphicsPipeline,
2662 bool secondSubpass)
2663 {
2664 const DeviceInterface &vkd = m_context.getDeviceInterface();
2665 VkDevice device = m_context.getDevice();
2666 const vk::BinaryCollection &binaryCollection = m_context.getBinaryCollection();
2667 VkSampleCountFlagBits sampleCount = sampleCountBitFromSampleCount(m_sampleCount);
2668 uint32_t blendStatesCount = m_attachmentsCount;
2669 std::string fragShaderNameBase = "quad-frag-sp0-";
2670
2671 if (secondSubpass)
2672 {
2673 sampleCount = VK_SAMPLE_COUNT_1_BIT;
2674 blendStatesCount /= 2;
2675 fragShaderNameBase = "quad-frag-sp1-";
2676 }
2677
2678 if (*m_renderPass == DE_NULL)
2679 blendStatesCount = m_attachmentsCount;
2680
2681 std::string fragShaderName = fragShaderNameBase + de::toString(m_attachmentsCount);
2682 ShaderWrapper vertexShaderModule(vkd, device, binaryCollection.get("quad-vert"), 0u);
2683 ShaderWrapper fragmentShaderModule(vkd, device, binaryCollection.get(fragShaderName), 0u);
2684 ShaderWrapper geometryShaderModule;
2685
2686 if (m_layerCount != 1)
2687 geometryShaderModule = ShaderWrapper(vkd, device, binaryCollection.get("geom"), 0u);
2688
2689 // Disable blending
2690 const VkPipelineColorBlendAttachmentState attachmentBlendState{
2691 VK_FALSE,
2692 VK_BLEND_FACTOR_SRC_ALPHA,
2693 VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
2694 VK_BLEND_OP_ADD,
2695 VK_BLEND_FACTOR_ONE,
2696 VK_BLEND_FACTOR_ONE,
2697 VK_BLEND_OP_ADD,
2698 VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT};
2699 std::vector<VkPipelineColorBlendAttachmentState> attachmentBlendStates(blendStatesCount, attachmentBlendState);
2700 const VkPipelineVertexInputStateCreateInfo vertexInputState = initVulkanStructure();
2701
2702 PipelineRenderingCreateInfoWrapper renderingCreateInfoWrapper;
2703 RenderingAttachmentLocationInfoWrapper renderingAttachmentLocationInfoWrapper;
2704 RenderingInputAttachmentIndexInfoWrapper renderingInputAttachmentIndexInfoWrapper;
2705 const tcu::UVec2 renderArea(m_width, m_height);
2706 const std::vector<VkViewport> viewports{makeViewport(renderArea)};
2707 const std::vector<VkRect2D> scissors{makeRect2D(renderArea)};
2708
2709 const VkPipelineMultisampleStateCreateInfo multisampleState = {
2710 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
2711 DE_NULL,
2712 (VkPipelineMultisampleStateCreateFlags)0u,
2713
2714 sampleCount,
2715 VK_FALSE,
2716 0.0f,
2717 DE_NULL,
2718 VK_FALSE,
2719 VK_FALSE,
2720 };
2721 const VkPipelineDepthStencilStateCreateInfo depthStencilState = {
2722 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
2723 DE_NULL,
2724 (VkPipelineDepthStencilStateCreateFlags)0u,
2725
2726 VK_FALSE,
2727 VK_TRUE,
2728 VK_COMPARE_OP_ALWAYS,
2729 VK_FALSE,
2730 VK_TRUE,
2731 {VK_STENCIL_OP_KEEP, VK_STENCIL_OP_INCREMENT_AND_WRAP, VK_STENCIL_OP_KEEP, VK_COMPARE_OP_ALWAYS, ~0u, ~0u,
2732 0xFFu / (m_sampleCount + 1)},
2733 {VK_STENCIL_OP_KEEP, VK_STENCIL_OP_INCREMENT_AND_WRAP, VK_STENCIL_OP_KEEP, VK_COMPARE_OP_ALWAYS, ~0u, ~0u,
2734 0xFFu / (m_sampleCount + 1)},
2735
2736 0.0f,
2737 1.0f};
2738 const VkPipelineColorBlendStateCreateInfo blendState{VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
2739 DE_NULL,
2740 (VkPipelineColorBlendStateCreateFlags)0u,
2741
2742 VK_FALSE,
2743 VK_LOGIC_OP_COPY,
2744 uint32_t(attachmentBlendStates.size()),
2745 attachmentBlendStates.data(),
2746 {0.0f, 0.0f, 0.0f, 0.0f}};
2747
2748 #ifndef CTS_USES_VULKANSC
2749 const std::vector<VkFormat> colorAttachmentFormats(m_attachmentsCount, m_format);
2750 VkPipelineRenderingCreateInfo renderingCreateInfo{VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO,
2751 DE_NULL,
2752 0u,
2753 (uint32_t)colorAttachmentFormats.size(),
2754 colorAttachmentFormats.data(),
2755 VK_FORMAT_UNDEFINED,
2756 VK_FORMAT_UNDEFINED};
2757
2758 std::vector<uint32_t> colorAttachmentLocationsAndInputs(colorAttachmentFormats.size());
2759 std::iota(colorAttachmentLocationsAndInputs.begin(), colorAttachmentLocationsAndInputs.end(), 0);
2760
2761 VkRenderingAttachmentLocationInfoKHR renderingAttachmentLocationInfo = initVulkanStructure();
2762 renderingAttachmentLocationInfo.colorAttachmentCount = (uint32_t)colorAttachmentFormats.size();
2763 renderingAttachmentLocationInfo.pColorAttachmentLocations = colorAttachmentLocationsAndInputs.data();
2764
2765 VkRenderingInputAttachmentIndexInfoKHR renderingInputAttachmentIndexInfo =
2766 initVulkanStructure(&renderingAttachmentLocationInfo);
2767 renderingInputAttachmentIndexInfo.colorAttachmentCount = (uint32_t)colorAttachmentLocationsAndInputs.size();
2768 renderingInputAttachmentIndexInfo.pColorAttachmentInputIndices = colorAttachmentLocationsAndInputs.data();
2769
2770 if (*m_renderPass == DE_NULL)
2771 {
2772 renderingCreateInfoWrapper.ptr = &renderingCreateInfo;
2773 renderingAttachmentLocationInfoWrapper.ptr = &renderingAttachmentLocationInfo;
2774 if (secondSubpass)
2775 renderingInputAttachmentIndexInfoWrapper.ptr = &renderingInputAttachmentIndexInfo;
2776 }
2777 #endif // CTS_USES_VULKANSC
2778
2779 PipelineLayoutWrapper &pipelineLayout(secondSubpass ? m_pipelineLayoutPass1 : m_pipelineLayoutPass0);
2780 graphicsPipeline.setDefaultRasterizationState()
2781 .setupVertexInputState(&vertexInputState)
2782 .setupPreRasterizationShaderState(viewports, scissors, pipelineLayout, *m_renderPass, secondSubpass,
2783 vertexShaderModule, 0u, ShaderWrapper(), ShaderWrapper(),
2784 geometryShaderModule, DE_NULL, DE_NULL, renderingCreateInfoWrapper)
2785 .setupFragmentShaderState(pipelineLayout, *m_renderPass, secondSubpass, fragmentShaderModule,
2786 &depthStencilState, &multisampleState, 0, 0, {},
2787 renderingInputAttachmentIndexInfoWrapper)
2788 .setupFragmentOutputState(*m_renderPass, secondSubpass, &blendState, &multisampleState, 0, {},
2789 renderingAttachmentLocationInfoWrapper)
2790 .setMonolithicPipelineLayout(pipelineLayout)
2791 .buildPipeline();
2792 }
2793
2794 class MultisampleRenderPassResolveLevelTestInstance : public MultisampleRenderPassTestInstance
2795 {
2796 public:
2797 MultisampleRenderPassResolveLevelTestInstance(Context &context, TestConfig2 config);
2798 ~MultisampleRenderPassResolveLevelTestInstance(void) = default;
2799 };
2800
MultisampleRenderPassResolveLevelTestInstance(Context & context,TestConfig2 config)2801 MultisampleRenderPassResolveLevelTestInstance::MultisampleRenderPassResolveLevelTestInstance(Context &context,
2802 TestConfig2 config)
2803 : MultisampleRenderPassTestInstance(context, config, config.resolveLevel)
2804 {
2805 }
2806
2807 struct Programs
2808 {
initvkt::__anon0c42d1a50111::Programs2809 void init(vk::SourceCollections &dst, TestConfig config) const
2810 {
2811 const tcu::TextureFormat format(mapVkFormat(config.format));
2812 const tcu::TextureChannelClass channelClass(tcu::getTextureChannelClass(format.type));
2813
2814 dst.glslSources.add("quad-vert") << glu::VertexSource(
2815 "#version 450\n"
2816 "out gl_PerVertex {\n"
2817 "\tvec4 gl_Position;\n"
2818 "};\n"
2819 "highp float;\n"
2820 "void main (void) {\n"
2821 "\tgl_Position = vec4(((gl_VertexIndex + 2) / 3) % 2 == 0 ? -1.0 : 1.0,\n"
2822 "\t ((gl_VertexIndex + 1) / 3) % 2 == 0 ? -1.0 : 1.0, 0.0, 1.0);\n"
2823 "}\n");
2824
2825 if (config.layerCount > 1)
2826 {
2827 std::ostringstream src;
2828
2829 src << "#version 450\n"
2830 << "highp float;\n"
2831 << "\n"
2832 << "layout(triangles) in;\n"
2833 << "layout(triangle_strip, max_vertices = " << 3 * 2 * config.layerCount << ") out;\n"
2834 << "\n"
2835 << "in gl_PerVertex {\n"
2836 << " vec4 gl_Position;\n"
2837 << "} gl_in[];\n"
2838 << "\n"
2839 << "out gl_PerVertex {\n"
2840 << " vec4 gl_Position;\n"
2841 << "};\n"
2842 << "\n"
2843 << "void main (void) {\n"
2844 << " for (int layerNdx = 0; layerNdx < " << config.layerCount << "; ++layerNdx) {\n"
2845 << " for(int vertexNdx = 0; vertexNdx < gl_in.length(); vertexNdx++) {\n"
2846 << " gl_Position = gl_in[vertexNdx].gl_Position;\n"
2847 << " gl_Layer = layerNdx;\n"
2848 << " EmitVertex();\n"
2849 << " };\n"
2850 << " EndPrimitive();\n"
2851 << " };\n"
2852 << "}\n";
2853
2854 dst.glslSources.add("geom") << glu::GeometrySource(src.str());
2855 }
2856
2857 const tcu::StringTemplate genericLayoutTemplate(
2858 "layout(location = ${INDEX}) out ${TYPE_PREFIX}vec4 o_color${INDEX};\n");
2859 const tcu::StringTemplate genericBodyTemplate("\to_color${INDEX} = ${TYPE_PREFIX}vec4(${COLOR_VAL});\n");
2860
2861 if (config.testType == RESOLVE || config.testType == COMPATIBILITY)
2862 {
2863 const tcu::StringTemplate fragTemplate("#version 450\n"
2864 "layout(push_constant) uniform PushConstant {\n"
2865 "\thighp uint sampleMask;\n"
2866 "} pushConstants;\n"
2867 "${LAYOUT}"
2868 "void main (void)\n"
2869 "{\n"
2870 "${BODY}"
2871 "}\n");
2872
2873 std::map<std::string, std::string> parameters;
2874 switch (channelClass)
2875 {
2876 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
2877 parameters["TYPE_PREFIX"] = "u";
2878 parameters["COLOR_VAL"] = "255";
2879 break;
2880
2881 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
2882 parameters["TYPE_PREFIX"] = "i";
2883 parameters["COLOR_VAL"] = "127";
2884 break;
2885
2886 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
2887 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
2888 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
2889 parameters["TYPE_PREFIX"] = "";
2890 parameters["COLOR_VAL"] = "1.0";
2891 break;
2892
2893 default:
2894 DE_FATAL("Unknown channel class");
2895 }
2896
2897 std::string layoutDefinitions = "";
2898 std::string shaderBody = "\tgl_SampleMask[0] = int(pushConstants.sampleMask);\n";
2899
2900 for (uint32_t attIdx = 0; attIdx < config.attachmentCount; ++attIdx)
2901 {
2902 parameters["INDEX"] = de::toString(attIdx);
2903 layoutDefinitions += genericLayoutTemplate.specialize(parameters);
2904 shaderBody += genericBodyTemplate.specialize(parameters);
2905 }
2906
2907 parameters["LAYOUT"] = layoutDefinitions;
2908 parameters["BODY"] = shaderBody;
2909 dst.glslSources.add("quad-frag") << glu::FragmentSource(fragTemplate.specialize(parameters));
2910 }
2911 else // MAX_ATTACMENTS
2912 {
2913 const tcu::StringTemplate fragTemplate("#version 450\n"
2914 "${LAYOUT}"
2915 "void main (void)\n"
2916 "{\n"
2917 "${BODY}"
2918 "}\n");
2919
2920 std::map<std::string, std::string> parameters;
2921 switch (channelClass)
2922 {
2923 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
2924 parameters["TYPE_PREFIX"] = "u";
2925 parameters["COLOR_VAL"] = "0, 64, 192, 252";
2926 break;
2927
2928 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
2929 parameters["TYPE_PREFIX"] = "i";
2930 parameters["COLOR_VAL"] = "0, 32, 100, 124";
2931 break;
2932
2933 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
2934 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
2935 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
2936 parameters["TYPE_PREFIX"] = "";
2937 parameters["COLOR_VAL"] = "0.0, 0.4, 0.8, 1.0";
2938 break;
2939
2940 default:
2941 DE_FATAL("Unknown channel class");
2942 }
2943
2944 // parts of fragment shader for second subpass - Vulkan introduced a new uniform type and syntax to glsl for input attachments
2945 const tcu::StringTemplate subpassLayoutTemplate(
2946 "layout (input_attachment_index = ${INDEX}, set = 0, binding = ${INDEX}) uniform "
2947 "${TYPE_PREFIX}subpassInput i_color${INDEX};\n");
2948 const tcu::StringTemplate subpassFBodyTemplate(
2949 "\to_color${INDEX} = subpassLoad(i_color${INDEX})*0.5 + subpassLoad(i_color${MIX_INDEX})*0.25;\n");
2950 const tcu::StringTemplate subpassIBodyTemplate(
2951 "\to_color${INDEX} = subpassLoad(i_color${INDEX}) / 2 + subpassLoad(i_color${MIX_INDEX}) / 4;\n");
2952
2953 bool selectIBody = isIntFormat(config.format) || isUintFormat(config.format);
2954 const tcu::StringTemplate &subpassBodyTemplate = selectIBody ? subpassIBodyTemplate : subpassFBodyTemplate;
2955
2956 std::string sp0layoutDefinitions = "";
2957 std::string sp0shaderBody = "";
2958 std::string sp1inLayoutDefinitions = "";
2959 std::string sp1outLayoutDefinitions = "";
2960 std::string sp1shaderBody = "";
2961
2962 uint32_t halfAttachments = config.attachmentCount / 2;
2963 for (uint32_t attIdx = 0; attIdx < config.attachmentCount; ++attIdx)
2964 {
2965 parameters["INDEX"] = de::toString(attIdx);
2966
2967 sp0layoutDefinitions += genericLayoutTemplate.specialize(parameters);
2968 sp0shaderBody += genericBodyTemplate.specialize(parameters);
2969
2970 sp1inLayoutDefinitions += subpassLayoutTemplate.specialize(parameters);
2971 if (attIdx < halfAttachments)
2972 {
2973 // we are combining pairs of input attachments to produce half the number of outputs
2974 parameters["MIX_INDEX"] = de::toString(halfAttachments + attIdx);
2975 sp1outLayoutDefinitions += genericLayoutTemplate.specialize(parameters);
2976 sp1shaderBody += subpassBodyTemplate.specialize(parameters);
2977 }
2978 }
2979
2980 // construct fragment shaders for subpass1 and subpass2; note that there
2981 // is different shader definition depending on number of attachments
2982 std::string nameBase = "quad-frag-sp";
2983 std::string namePostfix = de::toString(config.attachmentCount);
2984 parameters["LAYOUT"] = sp0layoutDefinitions;
2985 parameters["BODY"] = sp0shaderBody;
2986 dst.glslSources.add(nameBase + "0-" + namePostfix)
2987 << glu::FragmentSource(fragTemplate.specialize(parameters));
2988 parameters["LAYOUT"] = sp1inLayoutDefinitions + sp1outLayoutDefinitions;
2989 parameters["BODY"] = sp1shaderBody;
2990 dst.glslSources.add(nameBase + "1-" + namePostfix)
2991 << glu::FragmentSource(fragTemplate.specialize(parameters));
2992 }
2993 }
2994 };
2995
2996 template <class TestConfigType>
checkSupport(Context & context,TestConfigType config)2997 void checkSupport(Context &context, TestConfigType config)
2998 {
2999 #ifndef CTS_USES_VULKANSC
3000 if (config.format == VK_FORMAT_A8_UNORM_KHR)
3001 context.requireDeviceFunctionality("VK_KHR_maintenance5");
3002 #endif // CTS_USES_VULKANSC
3003
3004 if (config.layerCount > 1)
3005 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
3006
3007 if (config.groupParams->renderingType == RENDERING_TYPE_RENDERPASS2)
3008 context.requireDeviceFunctionality("VK_KHR_create_renderpass2");
3009
3010 const InstanceInterface &vki = context.getInstanceInterface();
3011 vk::VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
3012 const vk::VkPhysicalDeviceProperties properties = vk::getPhysicalDeviceProperties(vki, physicalDevice);
3013
3014 checkPipelineConstructionRequirements(vki, physicalDevice, config.groupParams->pipelineConstructionType);
3015 if (config.groupParams->renderingType == RENDERING_TYPE_DYNAMIC_RENDERING)
3016 {
3017 context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
3018 if (config.testType == MAX_ATTACHMENTS)
3019 {
3020 context.requireDeviceFunctionality("VK_KHR_dynamic_rendering_local_read");
3021 if (config.attachmentCount > properties.limits.maxColorAttachments)
3022 TCU_THROW(NotSupportedError, "Required number of color attachments not supported.");
3023 }
3024 }
3025
3026 #ifndef CTS_USES_VULKANSC
3027 if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
3028 !context.getPortabilitySubsetFeatures().multisampleArrayImage &&
3029 (config.sampleCount != VK_SAMPLE_COUNT_1_BIT) && (config.layerCount != 1))
3030 {
3031 TCU_THROW(
3032 NotSupportedError,
3033 "VK_KHR_portability_subset: Implementation does not support image array with multiple samples per texel");
3034 }
3035 #endif // CTS_USES_VULKANSC
3036
3037 if (config.attachmentCount > properties.limits.maxColorAttachments)
3038 TCU_THROW(NotSupportedError, "Required number of color attachments not supported.");
3039
3040 if (config.testType == MAX_ATTACHMENTS &&
3041 config.attachmentCount > properties.limits.maxPerStageDescriptorInputAttachments)
3042 TCU_THROW(NotSupportedError, "Required number of per stage descriptor input attachments not supported.");
3043 }
3044
formatToName(VkFormat format)3045 std::string formatToName(VkFormat format)
3046 {
3047 const std::string formatStr = de::toString(format);
3048 const std::string prefix = "VK_FORMAT_";
3049
3050 DE_ASSERT(formatStr.substr(0, prefix.length()) == prefix);
3051
3052 return de::toLower(formatStr.substr(prefix.length()));
3053 }
3054
initTests(tcu::TestCaseGroup * group,const SharedGroupParams groupParams)3055 void initTests(tcu::TestCaseGroup *group, const SharedGroupParams groupParams)
3056 {
3057 static const VkFormat formats[] = {
3058 VK_FORMAT_R5G6B5_UNORM_PACK16,
3059 VK_FORMAT_R8_UNORM,
3060 VK_FORMAT_R8_SNORM,
3061 VK_FORMAT_R8_UINT,
3062 VK_FORMAT_R8_SINT,
3063 #ifndef CTS_USES_VULKANSC
3064 VK_FORMAT_A8_UNORM_KHR,
3065 #endif // CTS_USES_VULKANSC
3066 VK_FORMAT_R8G8_UNORM,
3067 VK_FORMAT_R8G8_SNORM,
3068 VK_FORMAT_R8G8_UINT,
3069 VK_FORMAT_R8G8_SINT,
3070 VK_FORMAT_R8G8B8A8_UNORM,
3071 VK_FORMAT_R8G8B8A8_SNORM,
3072 VK_FORMAT_R8G8B8A8_UINT,
3073 VK_FORMAT_R8G8B8A8_SINT,
3074 VK_FORMAT_R8G8B8A8_SRGB,
3075 VK_FORMAT_A8B8G8R8_UNORM_PACK32,
3076 VK_FORMAT_A8B8G8R8_SNORM_PACK32,
3077 VK_FORMAT_A8B8G8R8_UINT_PACK32,
3078 VK_FORMAT_A8B8G8R8_SINT_PACK32,
3079 VK_FORMAT_A8B8G8R8_SRGB_PACK32,
3080 VK_FORMAT_B8G8R8A8_UNORM,
3081 VK_FORMAT_B8G8R8A8_SRGB,
3082 VK_FORMAT_A2R10G10B10_UNORM_PACK32,
3083 VK_FORMAT_A2B10G10R10_UNORM_PACK32,
3084 VK_FORMAT_A2B10G10R10_UINT_PACK32,
3085 VK_FORMAT_R16_UNORM,
3086 VK_FORMAT_R16_SNORM,
3087 VK_FORMAT_R16_UINT,
3088 VK_FORMAT_R16_SINT,
3089 VK_FORMAT_R16_SFLOAT,
3090 VK_FORMAT_R16G16_UNORM,
3091 VK_FORMAT_R16G16_SNORM,
3092 VK_FORMAT_R16G16_UINT,
3093 VK_FORMAT_R16G16_SINT,
3094 VK_FORMAT_R16G16_SFLOAT,
3095 VK_FORMAT_R16G16B16A16_UNORM,
3096 VK_FORMAT_R16G16B16A16_SNORM,
3097 VK_FORMAT_R16G16B16A16_UINT,
3098 VK_FORMAT_R16G16B16A16_SINT,
3099 VK_FORMAT_R16G16B16A16_SFLOAT,
3100 VK_FORMAT_R32_UINT,
3101 VK_FORMAT_R32_SINT,
3102 VK_FORMAT_R32_SFLOAT,
3103 VK_FORMAT_R32G32_UINT,
3104 VK_FORMAT_R32G32_SINT,
3105 VK_FORMAT_R32G32_SFLOAT,
3106 VK_FORMAT_R32G32B32A32_UINT,
3107 VK_FORMAT_R32G32B32A32_SINT,
3108 VK_FORMAT_R32G32B32A32_SFLOAT,
3109 VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16,
3110 };
3111 const uint32_t sampleCounts[] = {2u, 4u, 8u};
3112 const uint32_t layerCounts[] = {1u, 3u, 6u};
3113 const uint32_t resolveLevels[] = {2u, 3u, 4u};
3114 tcu::TestContext &testCtx(group->getTestContext());
3115
3116 for (size_t layerCountNdx = 0; layerCountNdx < DE_LENGTH_OF_ARRAY(layerCounts); layerCountNdx++)
3117 {
3118 const uint32_t layerCount(layerCounts[layerCountNdx]);
3119 const std::string layerGroupName("layers_" + de::toString(layerCount));
3120 de::MovePtr<tcu::TestCaseGroup> layerGroup(new tcu::TestCaseGroup(testCtx, layerGroupName.c_str()));
3121
3122 for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
3123 {
3124 const VkFormat format(formats[formatNdx]);
3125 const std::string formatName(formatToName(format));
3126 de::MovePtr<tcu::TestCaseGroup> formatGroup(new tcu::TestCaseGroup(testCtx, formatName.c_str()));
3127
3128 for (size_t sampleCountNdx = 0; sampleCountNdx < DE_LENGTH_OF_ARRAY(sampleCounts); sampleCountNdx++)
3129 {
3130 const uint32_t sampleCount(sampleCounts[sampleCountNdx]);
3131
3132 // Skip this test as it is rather slow
3133 if (layerCount == 6 && sampleCount == 8)
3134 continue;
3135
3136 // Reduce number of tests for dynamic rendering cases where secondary command buffer is used
3137 if (groupParams->useSecondaryCmdBuffer && ((sampleCount > 2u) || (layerCount > 3u)))
3138 continue;
3139
3140 std::string testName("samples_" + de::toString(sampleCount));
3141 const TestConfig testConfig{RESOLVE, format, sampleCount, layerCount, 0, 4u, 32u, 32u, groupParams};
3142
3143 // repeat only dynamic_rendering_local_read tests for GPL
3144 if (groupParams->pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
3145 {
3146 formatGroup->addChild(new InstanceFactory1WithSupport<MultisampleRenderPassTestInstance, TestConfig,
3147 FunctionSupport1<TestConfig>, Programs>(
3148 testCtx, testName.c_str(), testConfig,
3149 typename FunctionSupport1<TestConfig>::Args(checkSupport, testConfig)));
3150
3151 const TestConfig testConfigBaseLayer{RESOLVE, format, sampleCount, layerCount, 1,
3152 4u, 32u, 32u, groupParams};
3153 std::string testNameBaseLayer("samples_" + de::toString(sampleCount) + "_baseLayer1");
3154
3155 formatGroup->addChild(new InstanceFactory1WithSupport<MultisampleRenderPassTestInstance, TestConfig,
3156 FunctionSupport1<TestConfig>, Programs>(
3157 testCtx, testNameBaseLayer.c_str(), testConfigBaseLayer,
3158 typename FunctionSupport1<TestConfig>::Args(checkSupport, testConfigBaseLayer)));
3159
3160 for (uint32_t resolveLevel : resolveLevels)
3161 {
3162 const TestConfig2 testConfig2(testConfig, resolveLevel);
3163 std::string resolveLevelTestNameStr(testName + "_resolve_level_" + de::toString(resolveLevel));
3164 const char *resolveLevelTestName = resolveLevelTestNameStr.c_str();
3165
3166 formatGroup->addChild(
3167 new InstanceFactory1WithSupport<MultisampleRenderPassResolveLevelTestInstance, TestConfig2,
3168 FunctionSupport1<TestConfig2>, Programs>(
3169 testCtx, resolveLevelTestName, testConfig2,
3170 typename FunctionSupport1<TestConfig2>::Args(checkSupport, testConfig2)));
3171
3172 // Reduce number of tests for dynamic rendering cases where secondary command buffer is used
3173 if (groupParams->useSecondaryCmdBuffer)
3174 break;
3175 }
3176 }
3177
3178 // MaxAttachmenstsRenderPassTest is ment to test extreme cases where applications might consume all available on-chip
3179 // memory. This is achieved by using maxColorAttachments attachments and two subpasses, but during test creation we
3180 // dont know what is the maximal number of attachments (spirv tools are not available on all platforms) so we cant
3181 // construct shaders during test execution. To be able to test this we need to execute tests for all available
3182 // numbers of attachments despite the fact that we are only interested in the maximal number; test construction code
3183 // assumes that the number of attachments is power of two
3184 if ((layerCount == 1) && (groupParams->useSecondaryCmdBuffer ==
3185 groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass))
3186 {
3187 for (uint32_t power = 2; power < 5; ++power)
3188 {
3189 uint32_t attachmentCount = 1 << power;
3190 std::string maxAttName = "max_attachments_" + de::toString(attachmentCount) + "_" + testName;
3191
3192 TestConfig maxAttachmentsTestConfig = testConfig;
3193 maxAttachmentsTestConfig.testType = MAX_ATTACHMENTS;
3194 maxAttachmentsTestConfig.attachmentCount = attachmentCount;
3195
3196 formatGroup->addChild(
3197 new InstanceFactory1WithSupport<MaxAttachmenstsRenderPassTestInstance, TestConfig,
3198 FunctionSupport1<TestConfig>, Programs>(
3199 testCtx, maxAttName.c_str(), maxAttachmentsTestConfig,
3200 typename FunctionSupport1<TestConfig>::Args(checkSupport, maxAttachmentsTestConfig)));
3201 }
3202
3203 if (groupParams->renderingType != RENDERING_TYPE_DYNAMIC_RENDERING)
3204 {
3205 std::string compatibilityTestName = "compatibility_" + testName;
3206
3207 TestConfig compatibilityTestConfig = testConfig;
3208 compatibilityTestConfig.testType = COMPATIBILITY;
3209 compatibilityTestConfig.attachmentCount = 1;
3210
3211 formatGroup->addChild(
3212 new InstanceFactory1WithSupport<MultisampleRenderPassTestInstance, TestConfig,
3213 FunctionSupport1<TestConfig>, Programs>(
3214 testCtx, compatibilityTestName.c_str(), compatibilityTestConfig,
3215 typename FunctionSupport1<TestConfig>::Args(checkSupport, compatibilityTestConfig)));
3216 }
3217 }
3218 }
3219
3220 if (layerCount == 1)
3221 group->addChild(formatGroup.release());
3222 else
3223 layerGroup->addChild(formatGroup.release());
3224 }
3225
3226 if (layerCount != 1)
3227 group->addChild(layerGroup.release());
3228 }
3229 }
3230
3231 } // namespace
3232
createRenderPassMultisampleResolveTests(tcu::TestContext & testCtx,const renderpass::SharedGroupParams groupParams)3233 tcu::TestCaseGroup *createRenderPassMultisampleResolveTests(tcu::TestContext &testCtx,
3234 const renderpass::SharedGroupParams groupParams)
3235 {
3236 return createTestGroup(testCtx, "multisample_resolve", initTests, groupParams);
3237 }
3238
3239 } // namespace vkt
3240