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