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