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