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 passses with multisample attachments
22 *//*--------------------------------------------------------------------*/
23
24 #include "vktRenderPassMultisampleTests.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
52 #include "deUniquePtr.hpp"
53 #include "deSharedPtr.hpp"
54
55 using namespace vk;
56
57 using tcu::BVec4;
58 using tcu::IVec2;
59 using tcu::IVec4;
60 using tcu::UVec2;
61 using tcu::UVec4;
62 using tcu::Vec2;
63 using tcu::Vec4;
64
65 using tcu::Maybe;
66 using tcu::just;
67 using tcu::nothing;
68
69 using tcu::ConstPixelBufferAccess;
70 using tcu::PixelBufferAccess;
71
72 using tcu::TestLog;
73
74 using std::pair;
75 using std::string;
76 using std::vector;
77
78 typedef de::SharedPtr<vk::Unique<VkImage> > VkImageSp;
79 typedef de::SharedPtr<vk::Unique<VkImageView> > VkImageViewSp;
80 typedef de::SharedPtr<vk::Unique<VkBuffer> > VkBufferSp;
81 typedef de::SharedPtr<vk::Unique<VkPipeline> > VkPipelineSp;
82
83 namespace vkt
84 {
85 namespace
86 {
87 using namespace renderpass;
88
89 enum
90 {
91 MAX_COLOR_ATTACHMENT_COUNT = 4u
92 };
93
94 template<typename T>
safeSharedPtr(T * ptr)95 de::SharedPtr<T> safeSharedPtr (T* ptr)
96 {
97 try
98 {
99 return de::SharedPtr<T>(ptr);
100 }
101 catch (...)
102 {
103 delete ptr;
104 throw;
105 }
106 }
107
getImageAspectFlags(VkFormat vkFormat)108 VkImageAspectFlags getImageAspectFlags (VkFormat vkFormat)
109 {
110 const tcu::TextureFormat format (mapVkFormat(vkFormat));
111 const bool hasDepth (tcu::hasDepthComponent(format.order));
112 const bool hasStencil (tcu::hasStencilComponent(format.order));
113
114 if (hasDepth || hasStencil)
115 {
116 return (hasDepth ? VK_IMAGE_ASPECT_DEPTH_BIT : (VkImageAspectFlagBits)0u)
117 | (hasStencil ? VK_IMAGE_ASPECT_STENCIL_BIT : (VkImageAspectFlagBits)0u);
118 }
119 else
120 return VK_IMAGE_ASPECT_COLOR_BIT;
121 }
122
bindBufferMemory(const DeviceInterface & vk,VkDevice device,VkBuffer buffer,VkDeviceMemory mem,VkDeviceSize memOffset)123 void bindBufferMemory (const DeviceInterface& vk, VkDevice device, VkBuffer buffer, VkDeviceMemory mem, VkDeviceSize memOffset)
124 {
125 VK_CHECK(vk.bindBufferMemory(device, buffer, mem, memOffset));
126 }
127
bindImageMemory(const DeviceInterface & vk,VkDevice device,VkImage image,VkDeviceMemory mem,VkDeviceSize memOffset)128 void bindImageMemory (const DeviceInterface& vk, VkDevice device, VkImage image, VkDeviceMemory mem, VkDeviceSize memOffset)
129 {
130 VK_CHECK(vk.bindImageMemory(device, image, mem, memOffset));
131 }
132
createBufferMemory(const DeviceInterface & vk,VkDevice device,Allocator & allocator,VkBuffer buffer)133 de::MovePtr<Allocation> createBufferMemory (const DeviceInterface& vk,
134 VkDevice device,
135 Allocator& allocator,
136 VkBuffer buffer)
137 {
138 de::MovePtr<Allocation> allocation (allocator.allocate(getBufferMemoryRequirements(vk, device, buffer), MemoryRequirement::HostVisible));
139 bindBufferMemory(vk, device, buffer, allocation->getMemory(), allocation->getOffset());
140 return allocation;
141 }
142
createImageMemory(const DeviceInterface & vk,VkDevice device,Allocator & allocator,VkImage image)143 de::MovePtr<Allocation> createImageMemory (const DeviceInterface& vk,
144 VkDevice device,
145 Allocator& allocator,
146 VkImage image)
147 {
148 de::MovePtr<Allocation> allocation (allocator.allocate(getImageMemoryRequirements(vk, device, image), MemoryRequirement::Any));
149 bindImageMemory(vk, device, image, allocation->getMemory(), allocation->getOffset());
150 return allocation;
151 }
152
createImage(const DeviceInterface & vk,VkDevice device,VkImageCreateFlags flags,VkImageType imageType,VkFormat format,VkExtent3D extent,deUint32 mipLevels,deUint32 arrayLayers,VkSampleCountFlagBits samples,VkImageTiling tiling,VkImageUsageFlags usage,VkSharingMode sharingMode,deUint32 queueFamilyCount,const deUint32 * pQueueFamilyIndices,VkImageLayout initialLayout)153 Move<VkImage> createImage (const DeviceInterface& vk,
154 VkDevice device,
155 VkImageCreateFlags flags,
156 VkImageType imageType,
157 VkFormat format,
158 VkExtent3D extent,
159 deUint32 mipLevels,
160 deUint32 arrayLayers,
161 VkSampleCountFlagBits samples,
162 VkImageTiling tiling,
163 VkImageUsageFlags usage,
164 VkSharingMode sharingMode,
165 deUint32 queueFamilyCount,
166 const deUint32* pQueueFamilyIndices,
167 VkImageLayout initialLayout)
168 {
169 const VkImageCreateInfo pCreateInfo =
170 {
171 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
172 DE_NULL,
173 flags,
174 imageType,
175 format,
176 extent,
177 mipLevels,
178 arrayLayers,
179 samples,
180 tiling,
181 usage,
182 sharingMode,
183 queueFamilyCount,
184 pQueueFamilyIndices,
185 initialLayout
186 };
187 return createImage(vk, device, &pCreateInfo);
188 }
189
createImageView(const DeviceInterface & vk,VkDevice device,VkImageViewCreateFlags flags,VkImage image,VkImageViewType viewType,VkFormat format,VkComponentMapping components,VkImageSubresourceRange subresourceRange)190 Move<VkImageView> createImageView (const DeviceInterface& vk,
191 VkDevice device,
192 VkImageViewCreateFlags flags,
193 VkImage image,
194 VkImageViewType viewType,
195 VkFormat format,
196 VkComponentMapping components,
197 VkImageSubresourceRange subresourceRange)
198 {
199 const VkImageViewCreateInfo pCreateInfo =
200 {
201 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
202 DE_NULL,
203 flags,
204 image,
205 viewType,
206 format,
207 components,
208 subresourceRange,
209 };
210 return createImageView(vk, device, &pCreateInfo);
211 }
212
createImage(const InstanceInterface & vki,VkPhysicalDevice physicalDevice,const DeviceInterface & vkd,VkDevice device,VkFormat vkFormat,VkSampleCountFlagBits sampleCountBit,VkImageUsageFlags usage,deUint32 width,deUint32 height)213 Move<VkImage> createImage (const InstanceInterface& vki,
214 VkPhysicalDevice physicalDevice,
215 const DeviceInterface& vkd,
216 VkDevice device,
217 VkFormat vkFormat,
218 VkSampleCountFlagBits sampleCountBit,
219 VkImageUsageFlags usage,
220 deUint32 width,
221 deUint32 height)
222 {
223 try
224 {
225 const tcu::TextureFormat format (mapVkFormat(vkFormat));
226 const VkImageType imageType (VK_IMAGE_TYPE_2D);
227 const VkImageTiling imageTiling (VK_IMAGE_TILING_OPTIMAL);
228 const VkFormatProperties formatProperties (getPhysicalDeviceFormatProperties(vki, physicalDevice, vkFormat));
229 const VkImageFormatProperties imageFormatProperties (getPhysicalDeviceImageFormatProperties(vki, physicalDevice, vkFormat, imageType, imageTiling, usage, 0u));
230 const VkExtent3D imageExtent =
231 {
232 width,
233 height,
234 1u
235 };
236
237 if ((tcu::hasDepthComponent(format.order) || tcu::hasStencilComponent(format.order))
238 && (formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) == 0)
239 TCU_THROW(NotSupportedError, "Format can't be used as depth stencil attachment");
240
241 if (!(tcu::hasDepthComponent(format.order) || tcu::hasStencilComponent(format.order))
242 && (formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) == 0)
243 TCU_THROW(NotSupportedError, "Format can't be used as color attachment");
244
245 if (imageFormatProperties.maxExtent.width < imageExtent.width
246 || imageFormatProperties.maxExtent.height < imageExtent.height
247 || ((imageFormatProperties.sampleCounts & sampleCountBit) == 0))
248 {
249 TCU_THROW(NotSupportedError, "Image type not supported");
250 }
251
252 return createImage(vkd, device, 0u, imageType, vkFormat, imageExtent, 1u, 1u, sampleCountBit, imageTiling, usage, VK_SHARING_MODE_EXCLUSIVE, 0u, DE_NULL, VK_IMAGE_LAYOUT_UNDEFINED);
253 }
254 catch (const vk::Error& error)
255 {
256 if (error.getError() == VK_ERROR_FORMAT_NOT_SUPPORTED)
257 TCU_THROW(NotSupportedError, "Image format not supported");
258
259 throw;
260 }
261 }
262
createImageAttachmentView(const DeviceInterface & vkd,VkDevice device,VkImage image,VkFormat format,VkImageAspectFlags aspect)263 Move<VkImageView> createImageAttachmentView (const DeviceInterface& vkd,
264 VkDevice device,
265 VkImage image,
266 VkFormat format,
267 VkImageAspectFlags aspect)
268 {
269 const VkImageSubresourceRange range =
270 {
271 aspect,
272 0u,
273 1u,
274 0u,
275 1u
276 };
277
278 return createImageView(vkd, device, 0u, image, VK_IMAGE_VIEW_TYPE_2D, format, makeComponentMappingRGBA(), range);
279 }
280
createSrcPrimaryInputImageView(const DeviceInterface & vkd,VkDevice device,VkImage image,VkFormat format,VkImageAspectFlags aspect)281 Move<VkImageView> createSrcPrimaryInputImageView (const DeviceInterface& vkd,
282 VkDevice device,
283 VkImage image,
284 VkFormat format,
285 VkImageAspectFlags aspect)
286 {
287 const VkImageSubresourceRange range =
288 {
289 aspect == (VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_DEPTH_BIT)
290 ? (VkImageAspectFlags)VK_IMAGE_ASPECT_DEPTH_BIT
291 : aspect,
292 0u,
293 1u,
294 0u,
295 1u
296 };
297
298 return createImageView(vkd, device, 0u, image, VK_IMAGE_VIEW_TYPE_2D, format, makeComponentMappingRGBA(), range);
299 }
300
createSrcSecondaryInputImageView(const DeviceInterface & vkd,VkDevice device,VkImage image,VkFormat format,VkImageAspectFlags aspect)301 Move<VkImageView> createSrcSecondaryInputImageView (const DeviceInterface& vkd,
302 VkDevice device,
303 VkImage image,
304 VkFormat format,
305 VkImageAspectFlags aspect)
306 {
307 if (aspect == (VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_DEPTH_BIT))
308 {
309 const VkImageSubresourceRange range =
310 {
311 VK_IMAGE_ASPECT_STENCIL_BIT,
312 0u,
313 1u,
314 0u,
315 1u
316 };
317
318 return createImageView(vkd, device, 0u, image, VK_IMAGE_VIEW_TYPE_2D, format, makeComponentMappingRGBA(), range);
319 }
320 else
321 return Move<VkImageView>();
322 }
323
getPixelSize(VkFormat vkFormat)324 VkDeviceSize getPixelSize (VkFormat vkFormat)
325 {
326 const tcu::TextureFormat format (mapVkFormat(vkFormat));
327
328 return format.getPixelSize();
329 }
330
createBuffer(const DeviceInterface & vkd,VkDevice device,VkFormat format,deUint32 width,deUint32 height)331 Move<VkBuffer> createBuffer (const DeviceInterface& vkd,
332 VkDevice device,
333 VkFormat format,
334 deUint32 width,
335 deUint32 height)
336 {
337 const VkBufferUsageFlags bufferUsage (VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
338 const VkDeviceSize pixelSize (getPixelSize(format));
339 const VkBufferCreateInfo createInfo =
340 {
341 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
342 DE_NULL,
343 0u,
344
345 width * height * pixelSize,
346 bufferUsage,
347
348 VK_SHARING_MODE_EXCLUSIVE,
349 0u,
350 DE_NULL
351 };
352 return createBuffer(vkd, device, &createInfo);
353 }
354
sampleCountBitFromomSampleCount(deUint32 count)355 VkSampleCountFlagBits sampleCountBitFromomSampleCount (deUint32 count)
356 {
357 switch (count)
358 {
359 case 1: return VK_SAMPLE_COUNT_1_BIT;
360 case 2: return VK_SAMPLE_COUNT_2_BIT;
361 case 4: return VK_SAMPLE_COUNT_4_BIT;
362 case 8: return VK_SAMPLE_COUNT_8_BIT;
363 case 16: return VK_SAMPLE_COUNT_16_BIT;
364 case 32: return VK_SAMPLE_COUNT_32_BIT;
365 case 64: return VK_SAMPLE_COUNT_64_BIT;
366
367 default:
368 DE_FATAL("Invalid sample count");
369 return (VkSampleCountFlagBits)(0x1u << count);
370 }
371 }
372
createMultisampleImages(const InstanceInterface & vki,VkPhysicalDevice physicalDevice,const DeviceInterface & vkd,VkDevice device,VkFormat format,deUint32 sampleCount,deUint32 width,deUint32 height)373 std::vector<VkImageSp> createMultisampleImages (const InstanceInterface& vki,
374 VkPhysicalDevice physicalDevice,
375 const DeviceInterface& vkd,
376 VkDevice device,
377 VkFormat format,
378 deUint32 sampleCount,
379 deUint32 width,
380 deUint32 height)
381 {
382 std::vector<VkImageSp> images (sampleCount);
383
384 for (size_t imageNdx = 0; imageNdx < images.size(); imageNdx++)
385 images[imageNdx] = safeSharedPtr(new vk::Unique<VkImage>(createImage(vki, physicalDevice, vkd, device, format, sampleCountBitFromomSampleCount(sampleCount), VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, width, height)));
386
387 return images;
388 }
389
createSingleSampleImages(const InstanceInterface & vki,VkPhysicalDevice physicalDevice,const DeviceInterface & vkd,VkDevice device,VkFormat format,deUint32 sampleCount,deUint32 width,deUint32 height)390 std::vector<VkImageSp> createSingleSampleImages (const InstanceInterface& vki,
391 VkPhysicalDevice physicalDevice,
392 const DeviceInterface& vkd,
393 VkDevice device,
394 VkFormat format,
395 deUint32 sampleCount,
396 deUint32 width,
397 deUint32 height)
398 {
399 std::vector<VkImageSp> images (sampleCount);
400
401 for (size_t imageNdx = 0; imageNdx < images.size(); imageNdx++)
402 images[imageNdx] = safeSharedPtr(new vk::Unique<VkImage>(createImage(vki, physicalDevice, vkd, device, format, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, width, height)));
403
404 return images;
405 }
406
createImageMemory(const DeviceInterface & vkd,VkDevice device,Allocator & allocator,const std::vector<VkImageSp> images)407 std::vector<de::SharedPtr<Allocation> > createImageMemory (const DeviceInterface& vkd,
408 VkDevice device,
409 Allocator& allocator,
410 const std::vector<VkImageSp> images)
411 {
412 std::vector<de::SharedPtr<Allocation> > memory (images.size());
413
414 for (size_t memoryNdx = 0; memoryNdx < memory.size(); memoryNdx++)
415 memory[memoryNdx] = safeSharedPtr(createImageMemory(vkd, device, allocator, **images[memoryNdx]).release());
416
417 return memory;
418 }
419
createImageAttachmentViews(const DeviceInterface & vkd,VkDevice device,const std::vector<VkImageSp> & images,VkFormat format,VkImageAspectFlagBits aspect)420 std::vector<VkImageViewSp> createImageAttachmentViews (const DeviceInterface& vkd,
421 VkDevice device,
422 const std::vector<VkImageSp>& images,
423 VkFormat format,
424 VkImageAspectFlagBits aspect)
425 {
426 std::vector<VkImageViewSp> views (images.size());
427
428 for (size_t imageNdx = 0; imageNdx < images.size(); imageNdx++)
429 views[imageNdx] = safeSharedPtr(new vk::Unique<VkImageView>(createImageAttachmentView(vkd, device, **images[imageNdx], format, aspect)));
430
431 return views;
432 }
433
createBuffers(const DeviceInterface & vkd,VkDevice device,VkFormat format,deUint32 sampleCount,deUint32 width,deUint32 height)434 std::vector<VkBufferSp> createBuffers (const DeviceInterface& vkd,
435 VkDevice device,
436 VkFormat format,
437 deUint32 sampleCount,
438 deUint32 width,
439 deUint32 height)
440 {
441 std::vector<VkBufferSp> buffers (sampleCount);
442
443 for (size_t bufferNdx = 0; bufferNdx < buffers.size(); bufferNdx++)
444 buffers[bufferNdx] = safeSharedPtr(new vk::Unique<VkBuffer>(createBuffer(vkd, device, format, width, height)));
445
446 return buffers;
447 }
448
createBufferMemory(const DeviceInterface & vkd,VkDevice device,Allocator & allocator,const std::vector<VkBufferSp> buffers)449 std::vector<de::SharedPtr<Allocation> > createBufferMemory (const DeviceInterface& vkd,
450 VkDevice device,
451 Allocator& allocator,
452 const std::vector<VkBufferSp> buffers)
453 {
454 std::vector<de::SharedPtr<Allocation> > memory (buffers.size());
455
456 for (size_t memoryNdx = 0; memoryNdx < memory.size(); memoryNdx++)
457 memory[memoryNdx] = safeSharedPtr(createBufferMemory(vkd, device, allocator, **buffers[memoryNdx]).release());
458
459 return memory;
460 }
461
462 template<typename AttachmentDesc, typename AttachmentRef, typename SubpassDesc, typename SubpassDep, typename RenderPassCreateInfo>
createRenderPass(const DeviceInterface & vkd,VkDevice device,VkFormat srcFormat,VkFormat dstFormat,deUint32 sampleCount,RenderPassType renderPassType)463 Move<VkRenderPass> createRenderPass (const DeviceInterface& vkd,
464 VkDevice device,
465 VkFormat srcFormat,
466 VkFormat dstFormat,
467 deUint32 sampleCount,
468 RenderPassType renderPassType)
469 {
470 const VkSampleCountFlagBits samples (sampleCountBitFromomSampleCount(sampleCount));
471 const deUint32 splitSubpassCount (deDivRoundUp32(sampleCount, MAX_COLOR_ATTACHMENT_COUNT));
472 const tcu::TextureFormat format (mapVkFormat(srcFormat));
473 const bool isDepthStencilFormat (tcu::hasDepthComponent(format.order) || tcu::hasStencilComponent(format.order));
474 vector<SubpassDesc> subpasses;
475 vector<vector<AttachmentRef> > dstAttachmentRefs (splitSubpassCount);
476 vector<vector<AttachmentRef> > dstResolveAttachmentRefs (splitSubpassCount);
477 vector<AttachmentDesc> attachments;
478 vector<SubpassDep> dependencies;
479 const AttachmentRef srcAttachmentRef // VkAttachmentReference || VkAttachmentReference2KHR
480 (
481 // || VkStructureType sType;
482 DE_NULL, // || const void* pNext;
483 0u, // deUint32 attachment; || deUint32 attachment;
484 isDepthStencilFormat // VkImageLayout layout; || VkImageLayout layout;
485 ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
486 : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
487 0u // || VkImageAspectFlags aspectMask;
488 );
489 const AttachmentRef srcAttachmentInputRef // VkAttachmentReference || VkAttachmentReference2KHR
490 (
491 // || VkStructureType sType;
492 DE_NULL, // || const void* pNext;
493 0u, // deUint32 attachment; || deUint32 attachment;
494 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // VkImageLayout layout; || VkImageLayout layout;
495 (renderPassType == RENDERPASS_TYPE_RENDERPASS2) // || VkImageAspectFlags aspectMask;
496 ? getImageAspectFlags(srcFormat)
497 : 0u
498 );
499
500 {
501 const AttachmentDesc srcAttachment // VkAttachmentDescription || VkAttachmentDescription2KHR
502 (
503 // || VkStructureType sType;
504 DE_NULL, // || const void* pNext;
505 0u, // VkAttachmentDescriptionFlags flags; || VkAttachmentDescriptionFlags flags;
506 srcFormat, // VkFormat format; || VkFormat format;
507 samples, // VkSampleCountFlagBits samples; || VkSampleCountFlagBits samples;
508 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp loadOp; || VkAttachmentLoadOp loadOp;
509 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp storeOp; || VkAttachmentStoreOp storeOp;
510 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; || VkAttachmentLoadOp stencilLoadOp;
511 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; || VkAttachmentStoreOp stencilStoreOp;
512 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; || VkImageLayout initialLayout;
513 VK_IMAGE_LAYOUT_GENERAL // VkImageLayout finalLayout; || VkImageLayout finalLayout;
514 );
515
516 attachments.push_back(srcAttachment);
517 }
518
519 for (deUint32 splitSubpassIndex = 0; splitSubpassIndex < splitSubpassCount; splitSubpassIndex++)
520 {
521 for (deUint32 sampleNdx = 0; sampleNdx < de::min((deUint32)MAX_COLOR_ATTACHMENT_COUNT, sampleCount - splitSubpassIndex * MAX_COLOR_ATTACHMENT_COUNT); sampleNdx++)
522 {
523 // Multisample color attachment
524 {
525 const AttachmentDesc dstAttachment // VkAttachmentDescription || VkAttachmentDescription2KHR
526 (
527 // || VkStructureType sType;
528 DE_NULL, // || const void* pNext;
529 0u, // VkAttachmentDescriptionFlags flags; || VkAttachmentDescriptionFlags flags;
530 dstFormat, // VkFormat format; || VkFormat format;
531 samples, // VkSampleCountFlagBits samples; || VkSampleCountFlagBits samples;
532 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp loadOp; || VkAttachmentLoadOp loadOp;
533 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp storeOp; || VkAttachmentStoreOp storeOp;
534 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; || VkAttachmentLoadOp stencilLoadOp;
535 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; || VkAttachmentStoreOp stencilStoreOp;
536 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; || VkImageLayout initialLayout;
537 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout; || VkImageLayout finalLayout;
538 );
539 const AttachmentRef dstAttachmentRef // VkAttachmentReference || VkAttachmentReference2KHR
540 (
541 // || VkStructureType sType;
542 DE_NULL, // || const void* pNext;
543 (deUint32)attachments.size(), // deUint32 attachment; || deUint32 attachment;
544 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout layout; || VkImageLayout layout;
545 0u // || VkImageAspectFlags aspectMask;
546 );
547
548 attachments.push_back(dstAttachment);
549 dstAttachmentRefs[splitSubpassIndex].push_back(dstAttachmentRef);
550 }
551 // Resolve attachment
552 {
553 const AttachmentDesc dstAttachment // VkAttachmentDescription || VkAttachmentDescription2KHR
554 (
555 // || VkStructureType sType;
556 DE_NULL, // || const void* pNext;
557 0u, // VkAttachmentDescriptionFlags flags; || VkAttachmentDescriptionFlags flags;
558 dstFormat, // VkFormat format; || VkFormat format;
559 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; || VkSampleCountFlagBits samples;
560 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp loadOp; || VkAttachmentLoadOp loadOp;
561 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp; || VkAttachmentStoreOp storeOp;
562 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; || VkAttachmentLoadOp stencilLoadOp;
563 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp stencilStoreOp; || VkAttachmentStoreOp stencilStoreOp;
564 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; || VkImageLayout initialLayout;
565 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL // VkImageLayout finalLayout; || VkImageLayout finalLayout;
566 );
567 const AttachmentRef dstAttachmentRef // VkAttachmentReference || VkAttachmentReference2KHR
568 (
569 // || VkStructureType sType;
570 DE_NULL, // || const void* pNext;
571 (deUint32)attachments.size(), // deUint32 attachment; || deUint32 attachment;
572 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout layout; || VkImageLayout layout;
573 0u // || VkImageAspectFlags aspectMask;
574 );
575
576 attachments.push_back(dstAttachment);
577 dstResolveAttachmentRefs[splitSubpassIndex].push_back(dstAttachmentRef);
578 }
579 }
580 }
581
582 {
583 {
584 const SubpassDesc subpass // VkSubpassDescription || VkSubpassDescription2KHR
585 (
586 // || VkStructureType sType;
587 DE_NULL, // || const void* pNext;
588 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags; || VkSubpassDescriptionFlags flags;
589 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint; || VkPipelineBindPoint pipelineBindPoint;
590 0u, // || deUint32 viewMask;
591 0u, // deUint32 inputAttachmentCount; || deUint32 inputAttachmentCount;
592 DE_NULL, // const VkAttachmentReference* pInputAttachments; || const VkAttachmentReference2KHR* pInputAttachments;
593 isDepthStencilFormat ? 0u : 1u, // deUint32 colorAttachmentCount; || deUint32 colorAttachmentCount;
594 isDepthStencilFormat ? DE_NULL : &srcAttachmentRef, // const VkAttachmentReference* pColorAttachments; || const VkAttachmentReference2KHR* pColorAttachments;
595 DE_NULL, // const VkAttachmentReference* pResolveAttachments; || const VkAttachmentReference2KHR* pResolveAttachments;
596 isDepthStencilFormat ? &srcAttachmentRef : DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment; || const VkAttachmentReference2KHR* pDepthStencilAttachment;
597 0u, // deUint32 preserveAttachmentCount; || deUint32 preserveAttachmentCount;
598 DE_NULL // const deUint32* pPreserveAttachments; || const deUint32* pPreserveAttachments;
599 );
600
601 subpasses.push_back(subpass);
602 }
603
604 for (deUint32 splitSubpassIndex = 0; splitSubpassIndex < splitSubpassCount; splitSubpassIndex++)
605 {
606 {
607 const SubpassDesc subpass // VkSubpassDescription || VkSubpassDescription2KHR
608 (
609 // || VkStructureType sType;
610 DE_NULL, // || const void* pNext;
611 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags; || VkSubpassDescriptionFlags flags;
612 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint; || VkPipelineBindPoint pipelineBindPoint;
613 0u, // || deUint32 viewMask;
614 1u, // deUint32 inputAttachmentCount; || deUint32 inputAttachmentCount;
615 &srcAttachmentInputRef, // const VkAttachmentReference* pInputAttachments; || const VkAttachmentReference2KHR* pInputAttachments;
616 (deUint32)dstAttachmentRefs[splitSubpassIndex].size(), // deUint32 colorAttachmentCount; || deUint32 colorAttachmentCount;
617 &dstAttachmentRefs[splitSubpassIndex][0], // const VkAttachmentReference* pColorAttachments; || const VkAttachmentReference2KHR* pColorAttachments;
618 &dstResolveAttachmentRefs[splitSubpassIndex][0], // const VkAttachmentReference* pResolveAttachments; || const VkAttachmentReference2KHR* pResolveAttachments;
619 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment; || const VkAttachmentReference2KHR* pDepthStencilAttachment;
620 0u, // deUint32 preserveAttachmentCount; || deUint32 preserveAttachmentCount;
621 DE_NULL // const deUint32* pPreserveAttachments; || const deUint32* pPreserveAttachments;
622 );
623 subpasses.push_back(subpass);
624 }
625 {
626 const SubpassDep dependency // VkSubpassDependency || VkSubpassDependency2KHR
627 (
628 // || VkStructureType sType;
629 DE_NULL, // || const void* pNext;
630 0u, // deUint32 srcSubpass; || deUint32 srcSubpass;
631 splitSubpassIndex + 1, // deUint32 dstSubpass; || deUint32 dstSubpass;
632 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, // VkPipelineStageFlags srcStageMask; || VkPipelineStageFlags srcStageMask;
633 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, // VkPipelineStageFlags dstStageMask; || VkPipelineStageFlags dstStageMask;
634 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask; || VkAccessFlags srcAccessMask;
635 VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, // VkAccessFlags dstAccessMask; || VkAccessFlags dstAccessMask;
636 VK_DEPENDENCY_BY_REGION_BIT, // VkDependencyFlags dependencyFlags; || VkDependencyFlags dependencyFlags;
637 0u // || deInt32 viewOffset;
638 );
639
640 dependencies.push_back(dependency);
641 }
642 };
643 const RenderPassCreateInfo renderPassCreator // VkRenderPassCreateInfo || VkRenderPassCreateInfo2KHR
644 (
645 // VkStructureType sType; || VkStructureType sType;
646 DE_NULL, // const void* pNext; || const void* pNext;
647 (VkRenderPassCreateFlags)0u, // VkRenderPassCreateFlags flags; || VkRenderPassCreateFlags flags;
648 (deUint32)attachments.size(), // deUint32 attachmentCount; || deUint32 attachmentCount;
649 &attachments[0], // const VkAttachmentDescription* pAttachments; || const VkAttachmentDescription2KHR* pAttachments;
650 (deUint32)subpasses.size(), // deUint32 subpassCount; || deUint32 subpassCount;
651 &subpasses[0], // const VkSubpassDescription* pSubpasses; || const VkSubpassDescription2KHR* pSubpasses;
652 (deUint32)dependencies.size(), // deUint32 dependencyCount; || deUint32 dependencyCount;
653 &dependencies[0], // const VkSubpassDependency* pDependencies; || const VkSubpassDependency2KHR* pDependencies;
654 0u, // || deUint32 correlatedViewMaskCount;
655 DE_NULL // || const deUint32* pCorrelatedViewMasks;
656 );
657
658 return renderPassCreator.createRenderPass(vkd, device);
659 }
660 }
661
createRenderPass(const DeviceInterface & vkd,VkDevice device,VkFormat srcFormat,VkFormat dstFormat,deUint32 sampleCount,const RenderPassType renderPassType)662 Move<VkRenderPass> createRenderPass (const DeviceInterface& vkd,
663 VkDevice device,
664 VkFormat srcFormat,
665 VkFormat dstFormat,
666 deUint32 sampleCount,
667 const RenderPassType renderPassType)
668 {
669 switch (renderPassType)
670 {
671 case RENDERPASS_TYPE_LEGACY:
672 return createRenderPass<AttachmentDescription1, AttachmentReference1, SubpassDescription1, SubpassDependency1, RenderPassCreateInfo1>(vkd, device, srcFormat, dstFormat, sampleCount, renderPassType);
673 case RENDERPASS_TYPE_RENDERPASS2:
674 return createRenderPass<AttachmentDescription2, AttachmentReference2, SubpassDescription2, SubpassDependency2, RenderPassCreateInfo2>(vkd, device, srcFormat, dstFormat, sampleCount, renderPassType);
675 default:
676 TCU_THROW(InternalError, "Impossible");
677 }
678 }
679
createFramebuffer(const DeviceInterface & vkd,VkDevice device,VkRenderPass renderPass,VkImageView srcImageView,const std::vector<VkImageViewSp> & dstMultisampleImageViews,const std::vector<VkImageViewSp> & dstSinglesampleImageViews,deUint32 width,deUint32 height)680 Move<VkFramebuffer> createFramebuffer (const DeviceInterface& vkd,
681 VkDevice device,
682 VkRenderPass renderPass,
683 VkImageView srcImageView,
684 const std::vector<VkImageViewSp>& dstMultisampleImageViews,
685 const std::vector<VkImageViewSp>& dstSinglesampleImageViews,
686 deUint32 width,
687 deUint32 height)
688 {
689 std::vector<VkImageView> attachments;
690
691 attachments.reserve(dstMultisampleImageViews.size() + dstSinglesampleImageViews.size() + 1u);
692
693 attachments.push_back(srcImageView);
694
695 DE_ASSERT(dstMultisampleImageViews.size() == dstSinglesampleImageViews.size());
696
697 for (size_t ndx = 0; ndx < dstMultisampleImageViews.size(); ndx++)
698 {
699 attachments.push_back(**dstMultisampleImageViews[ndx]);
700 attachments.push_back(**dstSinglesampleImageViews[ndx]);
701 }
702
703 const VkFramebufferCreateInfo createInfo =
704 {
705 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
706 DE_NULL,
707 0u,
708
709 renderPass,
710 (deUint32)attachments.size(),
711 &attachments[0],
712
713 width,
714 height,
715 1u
716 };
717
718 return createFramebuffer(vkd, device, &createInfo);
719 }
720
createRenderPipelineLayout(const DeviceInterface & vkd,VkDevice device)721 Move<VkPipelineLayout> createRenderPipelineLayout (const DeviceInterface& vkd,
722 VkDevice device)
723 {
724 const VkPushConstantRange pushConstant =
725 {
726 VK_SHADER_STAGE_FRAGMENT_BIT,
727 0u,
728 4u
729 };
730 const VkPipelineLayoutCreateInfo createInfo =
731 {
732 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
733 DE_NULL,
734 (vk::VkPipelineLayoutCreateFlags)0,
735
736 0u,
737 DE_NULL,
738
739 1u,
740 &pushConstant
741 };
742
743 return createPipelineLayout(vkd, device, &createInfo);
744 }
745
createRenderPipeline(const DeviceInterface & vkd,VkDevice device,VkFormat srcFormat,VkRenderPass renderPass,VkPipelineLayout pipelineLayout,const vk::BinaryCollection & binaryCollection,deUint32 width,deUint32 height,deUint32 sampleCount)746 Move<VkPipeline> createRenderPipeline (const DeviceInterface& vkd,
747 VkDevice device,
748 VkFormat srcFormat,
749 VkRenderPass renderPass,
750 VkPipelineLayout pipelineLayout,
751 const vk::BinaryCollection& binaryCollection,
752 deUint32 width,
753 deUint32 height,
754 deUint32 sampleCount)
755 {
756 const tcu::TextureFormat format (mapVkFormat(srcFormat));
757 const bool isDepthStencilFormat (tcu::hasDepthComponent(format.order) || tcu::hasStencilComponent(format.order));
758
759 const Unique<VkShaderModule> vertexShaderModule (createShaderModule(vkd, device, binaryCollection.get("quad-vert"), 0u));
760 const Unique<VkShaderModule> fragmentShaderModule (createShaderModule(vkd, device, binaryCollection.get("quad-frag"), 0u));
761 // Disable blending
762 const VkPipelineColorBlendAttachmentState attachmentBlendState =
763 {
764 VK_FALSE,
765 VK_BLEND_FACTOR_SRC_ALPHA,
766 VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
767 VK_BLEND_OP_ADD,
768 VK_BLEND_FACTOR_ONE,
769 VK_BLEND_FACTOR_ONE,
770 VK_BLEND_OP_ADD,
771 VK_COLOR_COMPONENT_R_BIT|VK_COLOR_COMPONENT_G_BIT|VK_COLOR_COMPONENT_B_BIT|VK_COLOR_COMPONENT_A_BIT
772 };
773 const VkPipelineVertexInputStateCreateInfo vertexInputState =
774 {
775 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
776 DE_NULL,
777 (VkPipelineVertexInputStateCreateFlags)0u,
778
779 0u,
780 DE_NULL,
781
782 0u,
783 DE_NULL
784 };
785 const std::vector<VkViewport> viewports (1, makeViewport(tcu::UVec2(width, height)));
786 const std::vector<VkRect2D> scissors (1, makeRect2D(tcu::UVec2(width, height)));
787
788 const VkPipelineMultisampleStateCreateInfo multisampleState =
789 {
790 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
791 DE_NULL,
792 (VkPipelineMultisampleStateCreateFlags)0u,
793
794 sampleCountBitFromomSampleCount(sampleCount),
795 VK_FALSE,
796 0.0f,
797 DE_NULL,
798 VK_FALSE,
799 VK_FALSE,
800 };
801 const VkPipelineDepthStencilStateCreateInfo depthStencilState =
802 {
803 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
804 DE_NULL,
805 (VkPipelineDepthStencilStateCreateFlags)0u,
806
807 VK_TRUE,
808 VK_TRUE,
809 VK_COMPARE_OP_ALWAYS,
810 VK_FALSE,
811 VK_TRUE,
812 {
813 VK_STENCIL_OP_KEEP,
814 VK_STENCIL_OP_INCREMENT_AND_WRAP,
815 VK_STENCIL_OP_KEEP,
816 VK_COMPARE_OP_ALWAYS,
817 ~0u,
818 ~0u,
819 0xFFu / (sampleCount + 1)
820 },
821 {
822 VK_STENCIL_OP_KEEP,
823 VK_STENCIL_OP_INCREMENT_AND_WRAP,
824 VK_STENCIL_OP_KEEP,
825 VK_COMPARE_OP_ALWAYS,
826 ~0u,
827 ~0u,
828 0xFFu / (sampleCount + 1)
829 },
830
831 0.0f,
832 1.0f
833 };
834 const VkPipelineColorBlendStateCreateInfo blendState =
835 {
836 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
837 DE_NULL,
838 (VkPipelineColorBlendStateCreateFlags)0u,
839
840 VK_FALSE,
841 VK_LOGIC_OP_COPY,
842 (isDepthStencilFormat ? 0u : 1u),
843 (isDepthStencilFormat ? DE_NULL : &attachmentBlendState),
844 { 0.0f, 0.0f, 0.0f, 0.0f }
845 };
846
847 return makeGraphicsPipeline(vkd, // const DeviceInterface& vk
848 device, // const VkDevice device
849 pipelineLayout, // const VkPipelineLayout pipelineLayout
850 *vertexShaderModule, // const VkShaderModule vertexShaderModule
851 DE_NULL, // const VkShaderModule tessellationControlShaderModule
852 DE_NULL, // const VkShaderModule tessellationEvalShaderModule
853 DE_NULL, // const VkShaderModule geometryShaderModule
854 *fragmentShaderModule, // const VkShaderModule fragmentShaderModule
855 renderPass, // const VkRenderPass renderPass
856 viewports, // const std::vector<VkViewport>& viewports
857 scissors, // const std::vector<VkRect2D>& scissors
858 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // const VkPrimitiveTopology topology
859 0u, // const deUint32 subpass
860 0u, // const deUint32 patchControlPoints
861 &vertexInputState, // const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo
862 DE_NULL, // const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
863 &multisampleState, // const VkPipelineMultisampleStateCreateInfo* multisampleStateCreateInfo
864 &depthStencilState, // const VkPipelineDepthStencilStateCreateInfo* depthStencilStateCreateInfo
865 &blendState); // const VkPipelineColorBlendStateCreateInfo* colorBlendStateCreateInfo
866 }
867
createSplitDescriptorSetLayout(const DeviceInterface & vkd,VkDevice device,VkFormat vkFormat)868 Move<VkDescriptorSetLayout> createSplitDescriptorSetLayout (const DeviceInterface& vkd,
869 VkDevice device,
870 VkFormat vkFormat)
871 {
872 const tcu::TextureFormat format (mapVkFormat(vkFormat));
873 const bool hasDepth (tcu::hasDepthComponent(format.order));
874 const bool hasStencil (tcu::hasStencilComponent(format.order));
875 const VkDescriptorSetLayoutBinding bindings[] =
876 {
877 {
878 0u,
879 VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
880 1u,
881 VK_SHADER_STAGE_FRAGMENT_BIT,
882 DE_NULL
883 },
884 {
885 1u,
886 VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
887 1u,
888 VK_SHADER_STAGE_FRAGMENT_BIT,
889 DE_NULL
890 }
891 };
892 const VkDescriptorSetLayoutCreateInfo createInfo =
893 {
894 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
895 DE_NULL,
896 0u,
897
898 hasDepth && hasStencil ? 2u : 1u,
899 bindings
900 };
901
902 return createDescriptorSetLayout(vkd, device, &createInfo);
903 }
904
createSplitPipelineLayout(const DeviceInterface & vkd,VkDevice device,VkDescriptorSetLayout descriptorSetLayout)905 Move<VkPipelineLayout> createSplitPipelineLayout (const DeviceInterface& vkd,
906 VkDevice device,
907 VkDescriptorSetLayout descriptorSetLayout)
908 {
909 const VkPushConstantRange pushConstant =
910 {
911 VK_SHADER_STAGE_FRAGMENT_BIT,
912 0u,
913 4u
914 };
915 const VkPipelineLayoutCreateInfo createInfo =
916 {
917 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
918 DE_NULL,
919 (vk::VkPipelineLayoutCreateFlags)0,
920
921 1u,
922 &descriptorSetLayout,
923
924 1u,
925 &pushConstant
926 };
927
928 return createPipelineLayout(vkd, device, &createInfo);
929 }
930
createSplitPipeline(const DeviceInterface & vkd,VkDevice device,VkRenderPass renderPass,deUint32 subpassIndex,VkPipelineLayout pipelineLayout,const vk::BinaryCollection & binaryCollection,deUint32 width,deUint32 height,deUint32 sampleCount)931 Move<VkPipeline> createSplitPipeline (const DeviceInterface& vkd,
932 VkDevice device,
933 VkRenderPass renderPass,
934 deUint32 subpassIndex,
935 VkPipelineLayout pipelineLayout,
936 const vk::BinaryCollection& binaryCollection,
937 deUint32 width,
938 deUint32 height,
939 deUint32 sampleCount)
940 {
941 const Unique<VkShaderModule> vertexShaderModule (createShaderModule(vkd, device, binaryCollection.get("quad-vert"), 0u));
942 const Unique<VkShaderModule> fragmentShaderModule (createShaderModule(vkd, device, binaryCollection.get("quad-split-frag"), 0u));
943 // Disable blending
944 const VkPipelineColorBlendAttachmentState attachmentBlendState =
945 {
946 VK_FALSE,
947 VK_BLEND_FACTOR_SRC_ALPHA,
948 VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
949 VK_BLEND_OP_ADD,
950 VK_BLEND_FACTOR_ONE,
951 VK_BLEND_FACTOR_ONE,
952 VK_BLEND_OP_ADD,
953 VK_COLOR_COMPONENT_R_BIT|VK_COLOR_COMPONENT_G_BIT|VK_COLOR_COMPONENT_B_BIT|VK_COLOR_COMPONENT_A_BIT
954 };
955 const std::vector<VkPipelineColorBlendAttachmentState> attachmentBlendStates (de::min((deUint32)MAX_COLOR_ATTACHMENT_COUNT, sampleCount), attachmentBlendState);
956 const VkPipelineVertexInputStateCreateInfo vertexInputState =
957 {
958 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
959 DE_NULL,
960 (VkPipelineVertexInputStateCreateFlags)0u,
961
962 0u,
963 DE_NULL,
964
965 0u,
966 DE_NULL
967 };
968 const std::vector<VkViewport> viewports (1, makeViewport(tcu::UVec2(width, height)));
969 const std::vector<VkRect2D> scissors (1, makeRect2D(tcu::UVec2(width, height)));
970
971 const VkPipelineMultisampleStateCreateInfo multisampleState =
972 {
973 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
974 DE_NULL,
975 (VkPipelineMultisampleStateCreateFlags)0u,
976
977 sampleCountBitFromomSampleCount(sampleCount),
978 VK_FALSE,
979 0.0f,
980 DE_NULL,
981 VK_FALSE,
982 VK_FALSE,
983 };
984 const VkPipelineColorBlendStateCreateInfo blendState =
985 {
986 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
987 DE_NULL,
988 (VkPipelineColorBlendStateCreateFlags)0u,
989
990 VK_FALSE,
991 VK_LOGIC_OP_COPY,
992
993 (deUint32)attachmentBlendStates.size(),
994 &attachmentBlendStates[0],
995
996 { 0.0f, 0.0f, 0.0f, 0.0f }
997 };
998
999 return makeGraphicsPipeline(vkd, // const DeviceInterface& vk
1000 device, // const VkDevice device
1001 pipelineLayout, // const VkPipelineLayout pipelineLayout
1002 *vertexShaderModule, // const VkShaderModule vertexShaderModule
1003 DE_NULL, // const VkShaderModule tessellationControlShaderModule
1004 DE_NULL, // const VkShaderModule tessellationEvalShaderModule
1005 DE_NULL, // const VkShaderModule geometryShaderModule
1006 *fragmentShaderModule, // const VkShaderModule fragmentShaderModule
1007 renderPass, // const VkRenderPass renderPass
1008 viewports, // const std::vector<VkViewport>& viewports
1009 scissors, // const std::vector<VkRect2D>& scissors
1010 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // const VkPrimitiveTopology topology
1011 subpassIndex, // const deUint32 subpass
1012 0u, // const deUint32 patchControlPoints
1013 &vertexInputState, // const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo
1014 DE_NULL, // const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
1015 &multisampleState, // const VkPipelineMultisampleStateCreateInfo* multisampleStateCreateInfo
1016 DE_NULL, // const VkPipelineDepthStencilStateCreateInfo* depthStencilStateCreateInfo
1017 &blendState); // const VkPipelineColorBlendStateCreateInfo* colorBlendStateCreateInfo
1018 }
1019
createSplitPipelines(const DeviceInterface & vkd,VkDevice device,VkRenderPass renderPass,VkPipelineLayout pipelineLayout,const vk::BinaryCollection & binaryCollection,deUint32 width,deUint32 height,deUint32 sampleCount)1020 vector<VkPipelineSp> createSplitPipelines (const DeviceInterface& vkd,
1021 VkDevice device,
1022 VkRenderPass renderPass,
1023 VkPipelineLayout pipelineLayout,
1024 const vk::BinaryCollection& binaryCollection,
1025 deUint32 width,
1026 deUint32 height,
1027 deUint32 sampleCount)
1028 {
1029 std::vector<VkPipelineSp> pipelines (deDivRoundUp32(sampleCount, MAX_COLOR_ATTACHMENT_COUNT), (VkPipelineSp)0u);
1030
1031 for (size_t ndx = 0; ndx < pipelines.size(); ndx++)
1032 pipelines[ndx] = safeSharedPtr(new Unique<VkPipeline>(createSplitPipeline(vkd, device, renderPass, (deUint32)(ndx + 1), pipelineLayout, binaryCollection, width, height, sampleCount)));
1033
1034 return pipelines;
1035 }
1036
createSplitDescriptorPool(const DeviceInterface & vkd,VkDevice device)1037 Move<VkDescriptorPool> createSplitDescriptorPool (const DeviceInterface& vkd,
1038 VkDevice device)
1039 {
1040 const VkDescriptorPoolSize size =
1041 {
1042 VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 2u
1043 };
1044 const VkDescriptorPoolCreateInfo createInfo =
1045 {
1046 VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
1047 DE_NULL,
1048 VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
1049
1050
1051 2u,
1052 1u,
1053 &size
1054 };
1055
1056 return createDescriptorPool(vkd, device, &createInfo);
1057 }
1058
createSplitDescriptorSet(const DeviceInterface & vkd,VkDevice device,VkDescriptorPool pool,VkDescriptorSetLayout layout,VkImageView primaryImageView,VkImageView secondaryImageView)1059 Move<VkDescriptorSet> createSplitDescriptorSet (const DeviceInterface& vkd,
1060 VkDevice device,
1061 VkDescriptorPool pool,
1062 VkDescriptorSetLayout layout,
1063 VkImageView primaryImageView,
1064 VkImageView secondaryImageView)
1065 {
1066 const VkDescriptorSetAllocateInfo allocateInfo =
1067 {
1068 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
1069 DE_NULL,
1070
1071 pool,
1072 1u,
1073 &layout
1074 };
1075 Move<VkDescriptorSet> set (allocateDescriptorSet(vkd, device, &allocateInfo));
1076
1077 {
1078 const VkDescriptorImageInfo imageInfos[] =
1079 {
1080 {
1081 (VkSampler)0u,
1082 primaryImageView,
1083 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
1084 },
1085 {
1086 (VkSampler)0u,
1087 secondaryImageView,
1088 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
1089 }
1090 };
1091 const VkWriteDescriptorSet writes[] =
1092 {
1093 {
1094 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
1095 DE_NULL,
1096
1097 *set,
1098 0u,
1099 0u,
1100 1u,
1101 VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
1102 &imageInfos[0],
1103 DE_NULL,
1104 DE_NULL
1105 },
1106 {
1107 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
1108 DE_NULL,
1109
1110 *set,
1111 1u,
1112 0u,
1113 1u,
1114 VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
1115 &imageInfos[1],
1116 DE_NULL,
1117 DE_NULL
1118 }
1119 };
1120 const deUint32 count = secondaryImageView != (VkImageView)0
1121 ? 2u
1122 : 1u;
1123
1124 vkd.updateDescriptorSets(device, count, writes, 0u, DE_NULL);
1125 }
1126 return set;
1127 }
1128
1129 struct TestConfig
1130 {
TestConfigvkt::__anon7ad755d10111::TestConfig1131 TestConfig (VkFormat format_,
1132 deUint32 sampleCount_,
1133 RenderPassType renderPassType_)
1134 : format (format_)
1135 , sampleCount (sampleCount_)
1136 , renderPassType (renderPassType_)
1137 {
1138 }
1139
1140 VkFormat format;
1141 deUint32 sampleCount;
1142 RenderPassType renderPassType;
1143 };
1144
getSrcImageUsage(VkFormat vkFormat)1145 VkImageUsageFlags getSrcImageUsage (VkFormat vkFormat)
1146 {
1147 const tcu::TextureFormat format (mapVkFormat(vkFormat));
1148 const bool hasDepth (tcu::hasDepthComponent(format.order));
1149 const bool hasStencil (tcu::hasStencilComponent(format.order));
1150
1151 if (hasDepth || hasStencil)
1152 return VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
1153 else
1154 return VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
1155 }
1156
getDstFormat(VkFormat vkFormat)1157 VkFormat getDstFormat (VkFormat vkFormat)
1158 {
1159 const tcu::TextureFormat format (mapVkFormat(vkFormat));
1160 const bool hasDepth (tcu::hasDepthComponent(format.order));
1161 const bool hasStencil (tcu::hasStencilComponent(format.order));
1162
1163 if (hasDepth && hasStencil)
1164 return VK_FORMAT_R32G32_SFLOAT;
1165 else if (hasDepth || hasStencil)
1166 return VK_FORMAT_R32_SFLOAT;
1167 else
1168 return vkFormat;
1169 }
1170
1171
1172 class MultisampleRenderPassTestInstance : public TestInstance
1173 {
1174 public:
1175 MultisampleRenderPassTestInstance (Context& context, TestConfig config);
1176 ~MultisampleRenderPassTestInstance (void);
1177
1178 tcu::TestStatus iterate (void);
1179
1180 template<typename RenderpassSubpass>
1181 tcu::TestStatus iterateInternal (void);
1182
1183 private:
1184 const bool m_extensionSupported;
1185 const RenderPassType m_renderPassType;
1186
1187 const VkFormat m_srcFormat;
1188 const VkFormat m_dstFormat;
1189 const deUint32 m_sampleCount;
1190 const deUint32 m_width;
1191 const deUint32 m_height;
1192
1193 const VkImageAspectFlags m_srcImageAspect;
1194 const VkImageUsageFlags m_srcImageUsage;
1195 const Unique<VkImage> m_srcImage;
1196 const de::UniquePtr<Allocation> m_srcImageMemory;
1197 const Unique<VkImageView> m_srcImageView;
1198 const Unique<VkImageView> m_srcPrimaryInputImageView;
1199 const Unique<VkImageView> m_srcSecondaryInputImageView;
1200
1201 const std::vector<VkImageSp> m_dstMultisampleImages;
1202 const std::vector<de::SharedPtr<Allocation> > m_dstMultisampleImageMemory;
1203 const std::vector<VkImageViewSp> m_dstMultisampleImageViews;
1204
1205 const std::vector<VkImageSp> m_dstSinglesampleImages;
1206 const std::vector<de::SharedPtr<Allocation> > m_dstSinglesampleImageMemory;
1207 const std::vector<VkImageViewSp> m_dstSinglesampleImageViews;
1208
1209 const std::vector<VkBufferSp> m_dstBuffers;
1210 const std::vector<de::SharedPtr<Allocation> > m_dstBufferMemory;
1211
1212 const Unique<VkRenderPass> m_renderPass;
1213 const Unique<VkFramebuffer> m_framebuffer;
1214
1215 const Unique<VkPipelineLayout> m_renderPipelineLayout;
1216 const Unique<VkPipeline> m_renderPipeline;
1217
1218 const Unique<VkDescriptorSetLayout> m_splitDescriptorSetLayout;
1219 const Unique<VkPipelineLayout> m_splitPipelineLayout;
1220 const std::vector<VkPipelineSp> m_splitPipelines;
1221 const Unique<VkDescriptorPool> m_splitDescriptorPool;
1222 const Unique<VkDescriptorSet> m_splitDescriptorSet;
1223
1224 const Unique<VkCommandPool> m_commandPool;
1225 tcu::ResultCollector m_resultCollector;
1226 };
1227
MultisampleRenderPassTestInstance(Context & context,TestConfig config)1228 MultisampleRenderPassTestInstance::MultisampleRenderPassTestInstance (Context& context, TestConfig config)
1229 : TestInstance (context)
1230 , m_extensionSupported ((config.renderPassType == RENDERPASS_TYPE_RENDERPASS2) && context.requireDeviceExtension("VK_KHR_create_renderpass2"))
1231 , m_renderPassType (config.renderPassType)
1232 , m_srcFormat (config.format)
1233 , m_dstFormat (getDstFormat(config.format))
1234 , m_sampleCount (config.sampleCount)
1235 , m_width (32u)
1236 , m_height (32u)
1237
1238 , m_srcImageAspect (getImageAspectFlags(m_srcFormat))
1239 , m_srcImageUsage (getSrcImageUsage(m_srcFormat))
1240 , m_srcImage (createImage(context.getInstanceInterface(), context.getPhysicalDevice(), context.getDeviceInterface(), context.getDevice(), m_srcFormat, sampleCountBitFromomSampleCount(m_sampleCount), m_srcImageUsage, m_width, m_height))
1241 , m_srcImageMemory (createImageMemory(context.getDeviceInterface(), context.getDevice(), context.getDefaultAllocator(), *m_srcImage))
1242 , m_srcImageView (createImageAttachmentView(context.getDeviceInterface(), context.getDevice(), *m_srcImage, m_srcFormat, m_srcImageAspect))
1243 , m_srcPrimaryInputImageView (createSrcPrimaryInputImageView(context.getDeviceInterface(), context.getDevice(), *m_srcImage, m_srcFormat, m_srcImageAspect))
1244 , m_srcSecondaryInputImageView (createSrcSecondaryInputImageView(context.getDeviceInterface(), context.getDevice(), *m_srcImage, m_srcFormat, m_srcImageAspect))
1245
1246 , m_dstMultisampleImages (createMultisampleImages(context.getInstanceInterface(), context.getPhysicalDevice(), context.getDeviceInterface(), context.getDevice(), m_dstFormat, m_sampleCount, m_width, m_height))
1247 , m_dstMultisampleImageMemory (createImageMemory(context.getDeviceInterface(), context.getDevice(), context.getDefaultAllocator(), m_dstMultisampleImages))
1248 , m_dstMultisampleImageViews (createImageAttachmentViews(context.getDeviceInterface(), context.getDevice(), m_dstMultisampleImages, m_dstFormat, VK_IMAGE_ASPECT_COLOR_BIT))
1249
1250 , m_dstSinglesampleImages (createSingleSampleImages(context.getInstanceInterface(), context.getPhysicalDevice(), context.getDeviceInterface(), context.getDevice(), m_dstFormat, m_sampleCount, m_width, m_height))
1251 , m_dstSinglesampleImageMemory (createImageMemory(context.getDeviceInterface(), context.getDevice(), context.getDefaultAllocator(), m_dstSinglesampleImages))
1252 , m_dstSinglesampleImageViews (createImageAttachmentViews(context.getDeviceInterface(), context.getDevice(), m_dstSinglesampleImages, m_dstFormat, VK_IMAGE_ASPECT_COLOR_BIT))
1253
1254 , m_dstBuffers (createBuffers(context.getDeviceInterface(), context.getDevice(), m_dstFormat, m_sampleCount, m_width, m_height))
1255 , m_dstBufferMemory (createBufferMemory(context.getDeviceInterface(), context.getDevice(), context.getDefaultAllocator(), m_dstBuffers))
1256
1257 , m_renderPass (createRenderPass(context.getDeviceInterface(), context.getDevice(), m_srcFormat, m_dstFormat, m_sampleCount, config.renderPassType))
1258 , m_framebuffer (createFramebuffer(context.getDeviceInterface(), context.getDevice(), *m_renderPass, *m_srcImageView, m_dstMultisampleImageViews, m_dstSinglesampleImageViews, m_width, m_height))
1259
1260 , m_renderPipelineLayout (createRenderPipelineLayout(context.getDeviceInterface(), context.getDevice()))
1261 , m_renderPipeline (createRenderPipeline(context.getDeviceInterface(), context.getDevice(), m_srcFormat, *m_renderPass, *m_renderPipelineLayout, context.getBinaryCollection(), m_width, m_height, m_sampleCount))
1262
1263 , m_splitDescriptorSetLayout (createSplitDescriptorSetLayout(context.getDeviceInterface(), context.getDevice(), m_srcFormat))
1264 , m_splitPipelineLayout (createSplitPipelineLayout(context.getDeviceInterface(), context.getDevice(), *m_splitDescriptorSetLayout))
1265 , m_splitPipelines (createSplitPipelines(context.getDeviceInterface(), context.getDevice(), *m_renderPass, *m_splitPipelineLayout, context.getBinaryCollection(), m_width, m_height, m_sampleCount))
1266 , m_splitDescriptorPool (createSplitDescriptorPool(context.getDeviceInterface(), context.getDevice()))
1267 , m_splitDescriptorSet (createSplitDescriptorSet(context.getDeviceInterface(), context.getDevice(), *m_splitDescriptorPool, *m_splitDescriptorSetLayout, *m_srcPrimaryInputImageView, *m_srcSecondaryInputImageView))
1268 , m_commandPool (createCommandPool(context.getDeviceInterface(), context.getDevice(), VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, context.getUniversalQueueFamilyIndex()))
1269 {
1270 }
1271
~MultisampleRenderPassTestInstance(void)1272 MultisampleRenderPassTestInstance::~MultisampleRenderPassTestInstance (void)
1273 {
1274 }
1275
iterate(void)1276 tcu::TestStatus MultisampleRenderPassTestInstance::iterate (void)
1277 {
1278 switch (m_renderPassType)
1279 {
1280 case RENDERPASS_TYPE_LEGACY:
1281 return iterateInternal<RenderpassSubpass1>();
1282 case RENDERPASS_TYPE_RENDERPASS2:
1283 return iterateInternal<RenderpassSubpass2>();
1284 default:
1285 TCU_THROW(InternalError, "Impossible");
1286 }
1287 }
1288
1289 template<typename RenderpassSubpass>
iterateInternal(void)1290 tcu::TestStatus MultisampleRenderPassTestInstance::iterateInternal (void)
1291 {
1292 const DeviceInterface& vkd (m_context.getDeviceInterface());
1293 const VkDevice device (m_context.getDevice());
1294 const Unique<VkCommandBuffer> commandBuffer (allocateCommandBuffer(vkd, device, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1295 const typename RenderpassSubpass::SubpassBeginInfo subpassBeginInfo (DE_NULL, VK_SUBPASS_CONTENTS_INLINE);
1296 const typename RenderpassSubpass::SubpassEndInfo subpassEndInfo (DE_NULL);
1297
1298 beginCommandBuffer(vkd, *commandBuffer);
1299
1300 {
1301 const VkRenderPassBeginInfo beginInfo =
1302 {
1303 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
1304 DE_NULL,
1305
1306 *m_renderPass,
1307 *m_framebuffer,
1308
1309 {
1310 { 0u, 0u },
1311 { m_width, m_height }
1312 },
1313
1314 0u,
1315 DE_NULL
1316 };
1317 RenderpassSubpass::cmdBeginRenderPass(vkd, *commandBuffer, &beginInfo, &subpassBeginInfo);
1318
1319 // Stencil needs to be cleared if it exists.
1320 if (tcu::hasStencilComponent(mapVkFormat(m_srcFormat).order))
1321 {
1322 const VkClearAttachment clearAttachment =
1323 {
1324 VK_IMAGE_ASPECT_STENCIL_BIT, // VkImageAspectFlags aspectMask;
1325 0, // deUint32 colorAttachment;
1326 makeClearValueDepthStencil(0, 0) // VkClearValue clearValue;
1327 };
1328
1329 const VkClearRect clearRect =
1330 {
1331 {
1332 { 0u, 0u },
1333 { m_width, m_height }
1334 },
1335 0, // deUint32 baseArrayLayer;
1336 1 // deUint32 layerCount;
1337 };
1338
1339 vkd.cmdClearAttachments(*commandBuffer, 1, &clearAttachment, 1, &clearRect);
1340 }
1341 }
1342
1343 vkd.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_renderPipeline);
1344
1345 for (deUint32 sampleNdx = 0; sampleNdx < m_sampleCount; sampleNdx++)
1346 {
1347 vkd.cmdPushConstants(*commandBuffer, *m_renderPipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0u, sizeof(sampleNdx), &sampleNdx);
1348 vkd.cmdDraw(*commandBuffer, 6u, 1u, 0u, 0u);
1349 }
1350
1351 for (deUint32 splitPipelineNdx = 0; splitPipelineNdx < m_splitPipelines.size(); splitPipelineNdx++)
1352 {
1353 RenderpassSubpass::cmdNextSubpass(vkd, *commandBuffer, &subpassBeginInfo, &subpassEndInfo);
1354
1355 vkd.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **m_splitPipelines[splitPipelineNdx]);
1356 vkd.cmdBindDescriptorSets(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_splitPipelineLayout, 0u, 1u, &*m_splitDescriptorSet, 0u, DE_NULL);
1357 vkd.cmdPushConstants(*commandBuffer, *m_splitPipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0u, sizeof(splitPipelineNdx), &splitPipelineNdx);
1358 vkd.cmdDraw(*commandBuffer, 6u, 1u, 0u, 0u);
1359 }
1360
1361 RenderpassSubpass::cmdEndRenderPass(vkd, *commandBuffer, &subpassEndInfo);
1362
1363 for (size_t dstNdx = 0; dstNdx < m_dstSinglesampleImages.size(); dstNdx++)
1364 copyImageToBuffer(vkd, *commandBuffer, **m_dstSinglesampleImages[dstNdx], **m_dstBuffers[dstNdx], tcu::IVec2(m_width, m_height), VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
1365
1366 endCommandBuffer(vkd, *commandBuffer);
1367
1368 submitCommandsAndWait(vkd, device, m_context.getUniversalQueue(), *commandBuffer);
1369
1370 {
1371 const tcu::TextureFormat format (mapVkFormat(m_dstFormat));
1372 const tcu::TextureFormat srcFormat (mapVkFormat(m_srcFormat));
1373 const bool hasDepth (tcu::hasDepthComponent(srcFormat.order));
1374 const bool hasStencil (tcu::hasStencilComponent(srcFormat.order));
1375
1376 for (deUint32 sampleNdx = 0; sampleNdx < m_sampleCount; sampleNdx++)
1377 {
1378 Allocation *dstBufMem = m_dstBufferMemory[sampleNdx].get();
1379 invalidateAlloc(vkd, device, *dstBufMem);
1380
1381 const std::string name ("Sample" + de::toString(sampleNdx));
1382 const void* const ptr (dstBufMem->getHostPtr());
1383 const tcu::ConstPixelBufferAccess access (format, m_width, m_height, 1, ptr);
1384 tcu::TextureLevel reference (format, m_width, m_height);
1385
1386 if (hasDepth || hasStencil)
1387 {
1388 if (hasDepth)
1389 {
1390 for (deUint32 y = 0; y < m_height; y++)
1391 for (deUint32 x = 0; x < m_width; x++)
1392 {
1393 const deUint32 x1 = x ^ sampleNdx;
1394 const deUint32 y1 = y ^ sampleNdx;
1395 const float range = 1.0f;
1396 float depth = 0.0f;
1397 deUint32 divider = 2;
1398
1399 // \note Limited to ten bits since the target is 32x32, so there are 10 input bits
1400 for (size_t bitNdx = 0; bitNdx < 10; bitNdx++)
1401 {
1402 depth += (range / (float)divider)
1403 * (((bitNdx % 2 == 0 ? x1 : y1) & (0x1u << (bitNdx / 2u))) == 0u ? 0u : 1u);
1404 divider *= 2;
1405 }
1406
1407 reference.getAccess().setPixel(Vec4(depth, 0.0f, 0.0f, 0.0f), x, y);
1408 }
1409 }
1410 if (hasStencil)
1411 {
1412 for (deUint32 y = 0; y < m_height; y++)
1413 for (deUint32 x = 0; x < m_width; x++)
1414 {
1415 const deUint32 stencil = sampleNdx + 1u;
1416
1417 if (hasDepth)
1418 {
1419 const Vec4 src (reference.getAccess().getPixel(x, y));
1420
1421 reference.getAccess().setPixel(Vec4(src.x(), (float)stencil, 0.0f, 0.0f), x, y);
1422 }
1423 else
1424 reference.getAccess().setPixel(Vec4((float)stencil, 0.0f, 0.0f, 0.0f), x, y);
1425 }
1426 }
1427 {
1428 const Vec4 threshold (hasDepth ? (1.0f / 1024.0f) : 0.0f, 0.0f, 0.0f, 0.0f);
1429
1430 if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), name.c_str(), name.c_str(), reference.getAccess(), access, threshold, tcu::COMPARE_LOG_ON_ERROR))
1431 m_resultCollector.fail("Compare failed for sample " + de::toString(sampleNdx));
1432 }
1433 }
1434 else
1435 {
1436 const tcu::TextureChannelClass channelClass (tcu::getTextureChannelClass(format.type));
1437
1438 switch (channelClass)
1439 {
1440 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
1441 {
1442 const UVec4 bits (tcu::getTextureFormatBitDepth(format).cast<deUint32>());
1443 const UVec4 minValue (0);
1444 const UVec4 range (UVec4(1u) << tcu::min(bits, UVec4(31)));
1445 const int componentCount (tcu::getNumUsedChannels(format.order));
1446 const deUint32 bitSize (bits[0] + bits[1] + bits[2] + bits[3]);
1447
1448 for (deUint32 y = 0; y < m_height; y++)
1449 for (deUint32 x = 0; x < m_width; x++)
1450 {
1451 const deUint32 x1 = x ^ sampleNdx;
1452 const deUint32 y1 = y ^ sampleNdx;
1453 UVec4 color (minValue);
1454 deUint32 dstBitsUsed[4] = { 0u, 0u, 0u, 0u };
1455 deUint32 nextSrcBit = 0;
1456 deUint32 divider = 2;
1457
1458 // \note Limited to ten bits since the target is 32x32, so there are 10 input bits
1459 while (nextSrcBit < de::min(bitSize, 10u))
1460 {
1461 for (int compNdx = 0; compNdx < componentCount; compNdx++)
1462 {
1463 if (dstBitsUsed[compNdx] > bits[compNdx])
1464 continue;
1465
1466 color[compNdx] += (range[compNdx] / divider)
1467 * (((nextSrcBit % 2 == 0 ? x1 : y1) & (0x1u << (nextSrcBit / 2u))) == 0u ? 0u : 1u);
1468
1469 nextSrcBit++;
1470 dstBitsUsed[compNdx]++;
1471 }
1472
1473 divider *= 2;
1474 }
1475
1476 reference.getAccess().setPixel(color, x, y);
1477 }
1478
1479 if (!tcu::intThresholdCompare(m_context.getTestContext().getLog(), name.c_str(), name.c_str(), reference.getAccess(), access, UVec4(0u), tcu::COMPARE_LOG_ON_ERROR))
1480 m_resultCollector.fail("Compare failed for sample " + de::toString(sampleNdx));
1481
1482 break;
1483 }
1484
1485 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
1486 {
1487 const UVec4 bits (tcu::getTextureFormatBitDepth(format).cast<deUint32>());
1488 const IVec4 minValue (0);
1489 const IVec4 range ((UVec4(1u) << tcu::min(bits, UVec4(30))).cast<deInt32>());
1490 const int componentCount (tcu::getNumUsedChannels(format.order));
1491 const deUint32 bitSize (bits[0] + bits[1] + bits[2] + bits[3]);
1492
1493 for (deUint32 y = 0; y < m_height; y++)
1494 for (deUint32 x = 0; x < m_width; x++)
1495 {
1496 const deUint32 x1 = x ^ sampleNdx;
1497 const deUint32 y1 = y ^ sampleNdx;
1498 IVec4 color (minValue);
1499 deUint32 dstBitsUsed[4] = { 0u, 0u, 0u, 0u };
1500 deUint32 nextSrcBit = 0;
1501 deUint32 divider = 2;
1502
1503 // \note Limited to ten bits since the target is 32x32, so there are 10 input bits
1504 while (nextSrcBit < de::min(bitSize, 10u))
1505 {
1506 for (int compNdx = 0; compNdx < componentCount; compNdx++)
1507 {
1508 if (dstBitsUsed[compNdx] > bits[compNdx])
1509 continue;
1510
1511 color[compNdx] += (range[compNdx] / divider)
1512 * (((nextSrcBit % 2 == 0 ? x1 : y1) & (0x1u << (nextSrcBit / 2u))) == 0u ? 0u : 1u);
1513
1514 nextSrcBit++;
1515 dstBitsUsed[compNdx]++;
1516 }
1517
1518 divider *= 2;
1519 }
1520
1521 reference.getAccess().setPixel(color, x, y);
1522 }
1523
1524 if (!tcu::intThresholdCompare(m_context.getTestContext().getLog(), name.c_str(), name.c_str(), reference.getAccess(), access, UVec4(0u), tcu::COMPARE_LOG_ON_ERROR))
1525 m_resultCollector.fail("Compare failed for sample " + de::toString(sampleNdx));
1526
1527 break;
1528 }
1529
1530 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
1531 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
1532 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
1533 {
1534 const tcu::TextureFormatInfo info (tcu::getTextureFormatInfo(format));
1535 const UVec4 bits (tcu::getTextureFormatBitDepth(format).cast<deUint32>());
1536 const Vec4 minLimit (-65536.0);
1537 const Vec4 maxLimit (65536.0);
1538 const Vec4 minValue (tcu::max(info.valueMin, minLimit));
1539 const Vec4 range (tcu::min(info.valueMax, maxLimit) - minValue);
1540 const int componentCount (tcu::getNumUsedChannels(format.order));
1541 const deUint32 bitSize (bits[0] + bits[1] + bits[2] + bits[3]);
1542
1543 for (deUint32 y = 0; y < m_height; y++)
1544 for (deUint32 x = 0; x < m_width; x++)
1545 {
1546 const deUint32 x1 = x ^ sampleNdx;
1547 const deUint32 y1 = y ^ sampleNdx;
1548 Vec4 color (minValue);
1549 deUint32 dstBitsUsed[4] = { 0u, 0u, 0u, 0u };
1550 deUint32 nextSrcBit = 0;
1551 deUint32 divider = 2;
1552
1553 // \note Limited to ten bits since the target is 32x32, so there are 10 input bits
1554 while (nextSrcBit < de::min(bitSize, 10u))
1555 {
1556 for (int compNdx = 0; compNdx < componentCount; compNdx++)
1557 {
1558 if (dstBitsUsed[compNdx] > bits[compNdx])
1559 continue;
1560
1561 color[compNdx] += (range[compNdx] / (float)divider)
1562 * (((nextSrcBit % 2 == 0 ? x1 : y1) & (0x1u << (nextSrcBit / 2u))) == 0u ? 0u : 1u);
1563
1564 nextSrcBit++;
1565 dstBitsUsed[compNdx]++;
1566 }
1567
1568 divider *= 2;
1569 }
1570
1571 if (tcu::isSRGB(format))
1572 reference.getAccess().setPixel(tcu::linearToSRGB(color), x, y);
1573 else
1574 reference.getAccess().setPixel(color, x, y);
1575 }
1576
1577 if (channelClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT)
1578 {
1579 // Convert target format ulps to float ulps and allow 64ulp differences
1580 const UVec4 threshold (64u * (UVec4(1u) << (UVec4(23) - tcu::getTextureFormatMantissaBitDepth(format).cast<deUint32>())));
1581
1582 if (!tcu::floatUlpThresholdCompare(m_context.getTestContext().getLog(), name.c_str(), name.c_str(), reference.getAccess(), access, threshold, tcu::COMPARE_LOG_ON_ERROR))
1583 m_resultCollector.fail("Compare failed for sample " + de::toString(sampleNdx));
1584 }
1585 else
1586 {
1587 // Allow error of 4 times the minimum presentable difference
1588 const Vec4 threshold (4.0f * 1.0f / ((UVec4(1u) << tcu::getTextureFormatMantissaBitDepth(format).cast<deUint32>()) - 1u).cast<float>());
1589
1590 if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), name.c_str(), name.c_str(), reference.getAccess(), access, threshold, tcu::COMPARE_LOG_ON_ERROR))
1591 m_resultCollector.fail("Compare failed for sample " + de::toString(sampleNdx));
1592 }
1593
1594 break;
1595 }
1596
1597 default:
1598 DE_FATAL("Unknown channel class");
1599 }
1600 }
1601 }
1602 }
1603
1604 return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage());
1605 }
1606
1607 struct Programs
1608 {
initvkt::__anon7ad755d10111::Programs1609 void init (vk::SourceCollections& dst, TestConfig config) const
1610 {
1611 const tcu::TextureFormat format (mapVkFormat(config.format));
1612 const tcu::TextureChannelClass channelClass (tcu::getTextureChannelClass(format.type));
1613
1614 dst.glslSources.add("quad-vert") << glu::VertexSource(
1615 "#version 450\n"
1616 "out gl_PerVertex {\n"
1617 "\tvec4 gl_Position;\n"
1618 "};\n"
1619 "highp float;\n"
1620 "void main (void) {\n"
1621 "\tgl_Position = vec4(((gl_VertexIndex + 2) / 3) % 2 == 0 ? -1.0 : 1.0,\n"
1622 "\t ((gl_VertexIndex + 1) / 3) % 2 == 0 ? -1.0 : 1.0, 0.0, 1.0);\n"
1623 "}\n");
1624
1625 if (tcu::hasDepthComponent(format.order))
1626 {
1627 const Vec4 minValue (0.0f);
1628 const Vec4 range (1.0f);
1629 std::ostringstream fragmentShader;
1630
1631 fragmentShader <<
1632 "#version 450\n"
1633 "layout(push_constant) uniform PushConstant {\n"
1634 "\thighp uint sampleIndex;\n"
1635 "} pushConstants;\n"
1636 "void main (void)\n"
1637 "{\n"
1638 "\thighp uint sampleIndex = pushConstants.sampleIndex;\n"
1639 "\tgl_SampleMask[0] = int((~0x0u) << sampleIndex);\n"
1640 "\thighp float depth;\n"
1641 "\thighp uint x = sampleIndex ^ uint(gl_FragCoord.x);\n"
1642 "\thighp uint y = sampleIndex ^ uint(gl_FragCoord.y);\n";
1643
1644 fragmentShader << "\tdepth = " << minValue[0] << ";\n";
1645
1646 {
1647 deUint32 divider = 2;
1648
1649 // \note Limited to ten bits since the target is 32x32, so there are 10 input bits
1650 for (size_t bitNdx = 0; bitNdx < 10; bitNdx++)
1651 {
1652 fragmentShader <<
1653 "\tdepth += " << (range[0] / (float)divider)
1654 << " * float(bitfieldExtract(" << (bitNdx % 2 == 0 ? "x" : "y") << ", " << (bitNdx / 2) << ", 1));\n";
1655
1656 divider *= 2;
1657 }
1658 }
1659
1660 fragmentShader <<
1661 "\tgl_FragDepth = depth;\n"
1662 "}\n";
1663
1664 dst.glslSources.add("quad-frag") << glu::FragmentSource(fragmentShader.str());
1665 }
1666 else if (tcu::hasStencilComponent(format.order))
1667 {
1668 dst.glslSources.add("quad-frag") << glu::FragmentSource(
1669 "#version 450\n"
1670 "layout(push_constant) uniform PushConstant {\n"
1671 "\thighp uint sampleIndex;\n"
1672 "} pushConstants;\n"
1673 "void main (void)\n"
1674 "{\n"
1675 "\thighp uint sampleIndex = pushConstants.sampleIndex;\n"
1676 "\tgl_SampleMask[0] = int((~0x0u) << sampleIndex);\n"
1677 "}\n");
1678 }
1679 else
1680 {
1681 switch (channelClass)
1682 {
1683 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
1684 {
1685 const UVec4 bits (tcu::getTextureFormatBitDepth(format).cast<deUint32>());
1686 const UVec4 minValue (0);
1687 const UVec4 range (UVec4(1u) << tcu::min(bits, UVec4(31)));
1688 std::ostringstream fragmentShader;
1689
1690 fragmentShader <<
1691 "#version 450\n"
1692 "layout(location = 0) out highp uvec4 o_color;\n"
1693 "layout(push_constant) uniform PushConstant {\n"
1694 "\thighp uint sampleIndex;\n"
1695 "} pushConstants;\n"
1696 "void main (void)\n"
1697 "{\n"
1698 "\thighp uint sampleIndex = pushConstants.sampleIndex;\n"
1699 "\tgl_SampleMask[0] = int(0x1u << sampleIndex);\n"
1700 "\thighp uint color[4];\n"
1701 "\thighp uint x = sampleIndex ^ uint(gl_FragCoord.x);\n"
1702 "\thighp uint y = sampleIndex ^ uint(gl_FragCoord.y);\n";
1703
1704 for (int ndx = 0; ndx < 4; ndx++)
1705 fragmentShader << "\tcolor[" << ndx << "] = " << minValue[ndx] << ";\n";
1706
1707 {
1708 const int componentCount = tcu::getNumUsedChannels(format.order);
1709 const deUint32 bitSize (bits[0] + bits[1] + bits[2] + bits[3]);
1710 deUint32 dstBitsUsed[4] = { 0u, 0u, 0u, 0u };
1711 deUint32 nextSrcBit = 0;
1712 deUint32 divider = 2;
1713
1714 // \note Limited to ten bits since the target is 32x32, so there are 10 input bits
1715 while (nextSrcBit < de::min(bitSize, 10u))
1716 {
1717 for (int compNdx = 0; compNdx < componentCount; compNdx++)
1718 {
1719 if (dstBitsUsed[compNdx] > bits[compNdx])
1720 continue;
1721
1722 fragmentShader <<
1723 "\tcolor[" << compNdx << "] += " << (range[compNdx] / divider)
1724 << " * bitfieldExtract(" << (nextSrcBit % 2 == 0 ? "x" : "y") << ", " << (nextSrcBit / 2) << ", 1);\n";
1725
1726 nextSrcBit++;
1727 dstBitsUsed[compNdx]++;
1728 }
1729
1730 divider *= 2;
1731 }
1732 }
1733
1734 fragmentShader <<
1735 "\to_color = uvec4(color[0], color[1], color[2], color[3]);\n"
1736 "}\n";
1737
1738 dst.glslSources.add("quad-frag") << glu::FragmentSource(fragmentShader.str());
1739 break;
1740 }
1741
1742 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
1743 {
1744 const UVec4 bits (tcu::getTextureFormatBitDepth(format).cast<deUint32>());
1745 const IVec4 minValue (0);
1746 const IVec4 range ((UVec4(1u) << tcu::min(bits, UVec4(30))).cast<deInt32>());
1747 const IVec4 maxV ((UVec4(1u) << (bits - UVec4(1u))).cast<deInt32>());
1748 const IVec4 clampMax (maxV - 1);
1749 const IVec4 clampMin (-maxV);
1750 std::ostringstream fragmentShader;
1751
1752 fragmentShader <<
1753 "#version 450\n"
1754 "layout(location = 0) out highp ivec4 o_color;\n"
1755 "layout(push_constant) uniform PushConstant {\n"
1756 "\thighp uint sampleIndex;\n"
1757 "} pushConstants;\n"
1758 "void main (void)\n"
1759 "{\n"
1760 "\thighp uint sampleIndex = pushConstants.sampleIndex;\n"
1761 "\tgl_SampleMask[0] = int(0x1u << sampleIndex);\n"
1762 "\thighp int color[4];\n"
1763 "\thighp uint x = sampleIndex ^ uint(gl_FragCoord.x);\n"
1764 "\thighp uint y = sampleIndex ^ uint(gl_FragCoord.y);\n";
1765
1766 for (int ndx = 0; ndx < 4; ndx++)
1767 fragmentShader << "\tcolor[" << ndx << "] = " << minValue[ndx] << ";\n";
1768
1769 {
1770 const int componentCount = tcu::getNumUsedChannels(format.order);
1771 const deUint32 bitSize (bits[0] + bits[1] + bits[2] + bits[3]);
1772 deUint32 dstBitsUsed[4] = { 0u, 0u, 0u, 0u };
1773 deUint32 nextSrcBit = 0;
1774 deUint32 divider = 2;
1775
1776 // \note Limited to ten bits since the target is 32x32, so there are 10 input bits
1777 while (nextSrcBit < de::min(bitSize, 10u))
1778 {
1779 for (int compNdx = 0; compNdx < componentCount; compNdx++)
1780 {
1781 if (dstBitsUsed[compNdx] > bits[compNdx])
1782 continue;
1783
1784 fragmentShader <<
1785 "\tcolor[" << compNdx << "] += " << (range[compNdx] / divider)
1786 << " * int(bitfieldExtract(" << (nextSrcBit % 2 == 0 ? "x" : "y") << ", " << (nextSrcBit / 2) << ", 1));\n";
1787
1788 nextSrcBit++;
1789 dstBitsUsed[compNdx]++;
1790 }
1791
1792 divider *= 2;
1793 }
1794 }
1795
1796 // The spec doesn't define whether signed-integers are clamped on output,
1797 // so we'll clamp them explicitly to have well-defined outputs.
1798 fragmentShader <<
1799 "\to_color = clamp(ivec4(color[0], color[1], color[2], color[3]), " <<
1800 "ivec4" << clampMin << ", ivec4" << clampMax << ");\n" <<
1801 "}\n";
1802
1803 dst.glslSources.add("quad-frag") << glu::FragmentSource(fragmentShader.str());
1804 break;
1805 }
1806
1807 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
1808 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
1809 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
1810 {
1811 const tcu::TextureFormatInfo info (tcu::getTextureFormatInfo(format));
1812 const UVec4 bits (tcu::getTextureFormatMantissaBitDepth(format).cast<deUint32>());
1813 const Vec4 minLimit (-65536.0);
1814 const Vec4 maxLimit (65536.0);
1815 const Vec4 minValue (tcu::max(info.valueMin, minLimit));
1816 const Vec4 range (tcu::min(info.valueMax, maxLimit) - minValue);
1817 std::ostringstream fragmentShader;
1818
1819 fragmentShader <<
1820 "#version 450\n"
1821 "layout(location = 0) out highp vec4 o_color;\n"
1822 "layout(push_constant) uniform PushConstant {\n"
1823 "\thighp uint sampleIndex;\n"
1824 "} pushConstants;\n"
1825 "void main (void)\n"
1826 "{\n"
1827 "\thighp uint sampleIndex = pushConstants.sampleIndex;\n"
1828 "\tgl_SampleMask[0] = int(0x1u << sampleIndex);\n"
1829 "\thighp float color[4];\n"
1830 "\thighp uint x = sampleIndex ^ uint(gl_FragCoord.x);\n"
1831 "\thighp uint y = sampleIndex ^ uint(gl_FragCoord.y);\n";
1832
1833 for (int ndx = 0; ndx < 4; ndx++)
1834 fragmentShader << "\tcolor[" << ndx << "] = " << minValue[ndx] << ";\n";
1835
1836 {
1837 const int componentCount = tcu::getNumUsedChannels(format.order);
1838 const deUint32 bitSize (bits[0] + bits[1] + bits[2] + bits[3]);
1839 deUint32 dstBitsUsed[4] = { 0u, 0u, 0u, 0u };
1840 deUint32 nextSrcBit = 0;
1841 deUint32 divider = 2;
1842
1843 // \note Limited to ten bits since the target is 32x32, so there are 10 input bits
1844 while (nextSrcBit < de::min(bitSize, 10u))
1845 {
1846 for (int compNdx = 0; compNdx < componentCount; compNdx++)
1847 {
1848 if (dstBitsUsed[compNdx] > bits[compNdx])
1849 continue;
1850
1851 fragmentShader <<
1852 "\tcolor[" << compNdx << "] += " << (range[compNdx] / (float)divider)
1853 << " * float(bitfieldExtract(" << (nextSrcBit % 2 == 0 ? "x" : "y") << ", " << (nextSrcBit / 2) << ", 1));\n";
1854
1855 nextSrcBit++;
1856 dstBitsUsed[compNdx]++;
1857 }
1858
1859 divider *= 2;
1860 }
1861 }
1862
1863 fragmentShader <<
1864 "\to_color = vec4(color[0], color[1], color[2], color[3]);\n"
1865 "}\n";
1866
1867 dst.glslSources.add("quad-frag") << glu::FragmentSource(fragmentShader.str());
1868 break;
1869 }
1870
1871 default:
1872 DE_FATAL("Unknown channel class");
1873 }
1874 }
1875
1876 if (tcu::hasDepthComponent(format.order) || tcu::hasStencilComponent(format.order))
1877 {
1878 std::ostringstream splitShader;
1879
1880 splitShader <<
1881 "#version 450\n";
1882
1883 if (tcu::hasDepthComponent(format.order) && tcu::hasStencilComponent(format.order))
1884 {
1885 splitShader << "layout(input_attachment_index = 0, set = 0, binding = 0) uniform highp subpassInputMS i_depth;\n"
1886 << "layout(input_attachment_index = 0, set = 0, binding = 1) uniform highp usubpassInputMS i_stencil;\n";
1887 }
1888 else if (tcu::hasDepthComponent(format.order))
1889 splitShader << "layout(input_attachment_index = 0, set = 0, binding = 0) uniform highp subpassInputMS i_depth;\n";
1890 else if (tcu::hasStencilComponent(format.order))
1891 splitShader << "layout(input_attachment_index = 0, set = 0, binding = 0) uniform highp usubpassInputMS i_stencil;\n";
1892
1893 splitShader <<
1894 "layout(push_constant) uniform PushConstant {\n"
1895 "\thighp uint splitSubpassIndex;\n"
1896 "} pushConstants;\n";
1897
1898 for (deUint32 attachmentNdx = 0; attachmentNdx < de::min((deUint32)MAX_COLOR_ATTACHMENT_COUNT, config.sampleCount); attachmentNdx++)
1899 {
1900 if (tcu::hasDepthComponent(format.order) && tcu::hasStencilComponent(format.order))
1901 splitShader << "layout(location = " << attachmentNdx << ") out highp vec2 o_color" << attachmentNdx << ";\n";
1902 else
1903 splitShader << "layout(location = " << attachmentNdx << ") out highp float o_color" << attachmentNdx << ";\n";
1904 }
1905
1906 splitShader <<
1907 "void main (void)\n"
1908 "{\n";
1909
1910 for (deUint32 attachmentNdx = 0; attachmentNdx < de::min((deUint32)MAX_COLOR_ATTACHMENT_COUNT, config.sampleCount); attachmentNdx++)
1911 {
1912 if (tcu::hasDepthComponent(format.order))
1913 splitShader << "\thighp float depth" << attachmentNdx << " = subpassLoad(i_depth, int(" << MAX_COLOR_ATTACHMENT_COUNT << " * pushConstants.splitSubpassIndex + " << attachmentNdx << "u)).x;\n";
1914
1915 if (tcu::hasStencilComponent(format.order))
1916 splitShader << "\thighp uint stencil" << attachmentNdx << " = subpassLoad(i_stencil, int(" << MAX_COLOR_ATTACHMENT_COUNT << " * pushConstants.splitSubpassIndex + " << attachmentNdx << "u)).x;\n";
1917
1918 if (tcu::hasDepthComponent(format.order) && tcu::hasStencilComponent(format.order))
1919 splitShader << "\to_color" << attachmentNdx << " = vec2(depth" << attachmentNdx << ", float(stencil" << attachmentNdx << "));\n";
1920 else if (tcu::hasDepthComponent(format.order))
1921 splitShader << "\to_color" << attachmentNdx << " = float(depth" << attachmentNdx << ");\n";
1922 else if (tcu::hasStencilComponent(format.order))
1923 splitShader << "\to_color" << attachmentNdx << " = float(stencil" << attachmentNdx << ");\n";
1924 }
1925
1926 splitShader <<
1927 "}\n";
1928
1929 dst.glslSources.add("quad-split-frag") << glu::FragmentSource(splitShader.str());
1930 }
1931 else
1932 {
1933 std::string subpassType;
1934 std::string outputType;
1935
1936 switch (channelClass)
1937 {
1938 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
1939 subpassType = "usubpassInputMS";
1940 outputType = "uvec4";
1941 break;
1942
1943 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
1944 subpassType = "isubpassInputMS";
1945 outputType = "ivec4";
1946 break;
1947
1948 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
1949 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
1950 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
1951 subpassType = "subpassInputMS";
1952 outputType = "vec4";
1953 break;
1954
1955 default:
1956 DE_FATAL("Unknown channel class");
1957 }
1958
1959 std::ostringstream splitShader;
1960 splitShader <<
1961 "#version 450\n"
1962 "layout(input_attachment_index = 0, set = 0, binding = 0) uniform highp " << subpassType << " i_color;\n"
1963 "layout(push_constant) uniform PushConstant {\n"
1964 "\thighp uint splitSubpassIndex;\n"
1965 "} pushConstants;\n";
1966
1967 for (deUint32 attachmentNdx = 0; attachmentNdx < de::min((deUint32)MAX_COLOR_ATTACHMENT_COUNT, config.sampleCount); attachmentNdx++)
1968 splitShader << "layout(location = " << attachmentNdx << ") out highp " << outputType << " o_color" << attachmentNdx << ";\n";
1969
1970 splitShader <<
1971 "void main (void)\n"
1972 "{\n";
1973
1974 for (deUint32 attachmentNdx = 0; attachmentNdx < de::min((deUint32)MAX_COLOR_ATTACHMENT_COUNT, config.sampleCount); attachmentNdx++)
1975 splitShader << "\to_color" << attachmentNdx << " = subpassLoad(i_color, int(" << MAX_COLOR_ATTACHMENT_COUNT << " * pushConstants.splitSubpassIndex + " << attachmentNdx << "u));\n";
1976
1977 splitShader <<
1978 "}\n";
1979
1980 dst.glslSources.add("quad-split-frag") << glu::FragmentSource(splitShader.str());
1981 }
1982 }
1983 };
1984
formatToName(VkFormat format)1985 std::string formatToName (VkFormat format)
1986 {
1987 const std::string formatStr = de::toString(format);
1988 const std::string prefix = "VK_FORMAT_";
1989
1990 DE_ASSERT(formatStr.substr(0, prefix.length()) == prefix);
1991
1992 return de::toLower(formatStr.substr(prefix.length()));
1993 }
1994
initTests(tcu::TestCaseGroup * group,RenderPassType renderPassType)1995 void initTests (tcu::TestCaseGroup* group, RenderPassType renderPassType)
1996 {
1997 static const VkFormat formats[] =
1998 {
1999 VK_FORMAT_R5G6B5_UNORM_PACK16,
2000 VK_FORMAT_R8_UNORM,
2001 VK_FORMAT_R8_SNORM,
2002 VK_FORMAT_R8_UINT,
2003 VK_FORMAT_R8_SINT,
2004 VK_FORMAT_R8G8_UNORM,
2005 VK_FORMAT_R8G8_SNORM,
2006 VK_FORMAT_R8G8_UINT,
2007 VK_FORMAT_R8G8_SINT,
2008 VK_FORMAT_R8G8B8A8_UNORM,
2009 VK_FORMAT_R8G8B8A8_SNORM,
2010 VK_FORMAT_R8G8B8A8_UINT,
2011 VK_FORMAT_R8G8B8A8_SINT,
2012 VK_FORMAT_R8G8B8A8_SRGB,
2013 VK_FORMAT_A8B8G8R8_UNORM_PACK32,
2014 VK_FORMAT_A8B8G8R8_SNORM_PACK32,
2015 VK_FORMAT_A8B8G8R8_UINT_PACK32,
2016 VK_FORMAT_A8B8G8R8_SINT_PACK32,
2017 VK_FORMAT_A8B8G8R8_SRGB_PACK32,
2018 VK_FORMAT_B8G8R8A8_UNORM,
2019 VK_FORMAT_B8G8R8A8_SRGB,
2020 VK_FORMAT_A2R10G10B10_UNORM_PACK32,
2021 VK_FORMAT_A2B10G10R10_UNORM_PACK32,
2022 VK_FORMAT_A2B10G10R10_UINT_PACK32,
2023 VK_FORMAT_R16_UNORM,
2024 VK_FORMAT_R16_SNORM,
2025 VK_FORMAT_R16_UINT,
2026 VK_FORMAT_R16_SINT,
2027 VK_FORMAT_R16_SFLOAT,
2028 VK_FORMAT_R16G16_UNORM,
2029 VK_FORMAT_R16G16_SNORM,
2030 VK_FORMAT_R16G16_UINT,
2031 VK_FORMAT_R16G16_SINT,
2032 VK_FORMAT_R16G16_SFLOAT,
2033 VK_FORMAT_R16G16B16A16_UNORM,
2034 VK_FORMAT_R16G16B16A16_SNORM,
2035 VK_FORMAT_R16G16B16A16_UINT,
2036 VK_FORMAT_R16G16B16A16_SINT,
2037 VK_FORMAT_R16G16B16A16_SFLOAT,
2038 VK_FORMAT_R32_UINT,
2039 VK_FORMAT_R32_SINT,
2040 VK_FORMAT_R32_SFLOAT,
2041 VK_FORMAT_R32G32_UINT,
2042 VK_FORMAT_R32G32_SINT,
2043 VK_FORMAT_R32G32_SFLOAT,
2044 VK_FORMAT_R32G32B32A32_UINT,
2045 VK_FORMAT_R32G32B32A32_SINT,
2046 VK_FORMAT_R32G32B32A32_SFLOAT,
2047
2048 VK_FORMAT_D16_UNORM,
2049 VK_FORMAT_X8_D24_UNORM_PACK32,
2050 VK_FORMAT_D32_SFLOAT,
2051 VK_FORMAT_S8_UINT,
2052 VK_FORMAT_D16_UNORM_S8_UINT,
2053 VK_FORMAT_D24_UNORM_S8_UINT,
2054 VK_FORMAT_D32_SFLOAT_S8_UINT
2055 };
2056 const deUint32 sampleCounts[] =
2057 {
2058 2u, 4u, 8u, 16u, 32u
2059 };
2060 tcu::TestContext& testCtx (group->getTestContext());
2061
2062 for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
2063 {
2064 const VkFormat format (formats[formatNdx]);
2065 const std::string formatName (formatToName(format));
2066 de::MovePtr<tcu::TestCaseGroup> formatGroup (new tcu::TestCaseGroup(testCtx, formatName.c_str(), formatName.c_str()));
2067
2068 for (size_t sampleCountNdx = 0; sampleCountNdx < DE_LENGTH_OF_ARRAY(sampleCounts); sampleCountNdx++)
2069 {
2070 const deUint32 sampleCount (sampleCounts[sampleCountNdx]);
2071 const TestConfig testConfig (format, sampleCount, renderPassType);
2072 const std::string testName ("samples_" + de::toString(sampleCount));
2073
2074 formatGroup->addChild(new InstanceFactory1<MultisampleRenderPassTestInstance, TestConfig, Programs>(testCtx, tcu::NODETYPE_SELF_VALIDATE, testName.c_str(), testName.c_str(), testConfig));
2075 }
2076
2077 group->addChild(formatGroup.release());
2078 }
2079 }
2080
2081 } // anonymous
2082
createRenderPassMultisampleTests(tcu::TestContext & testCtx)2083 tcu::TestCaseGroup* createRenderPassMultisampleTests (tcu::TestContext& testCtx)
2084 {
2085 return createTestGroup(testCtx, "multisample", "Multisample render pass tests", initTests, RENDERPASS_TYPE_LEGACY);
2086 }
2087
createRenderPass2MultisampleTests(tcu::TestContext & testCtx)2088 tcu::TestCaseGroup* createRenderPass2MultisampleTests (tcu::TestContext& testCtx)
2089 {
2090 return createTestGroup(testCtx, "multisample", "Multisample render pass tests", initTests, RENDERPASS_TYPE_RENDERPASS2);
2091 }
2092
2093 } // vkt
2094