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