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 "vkBarrierUtil.hpp"
38 #include "vkRef.hpp"
39 #include "vkRefUtil.hpp"
40 #include "vkTypeUtil.hpp"
41 #include "vkCmdUtil.hpp"
42 #include "vkObjUtil.hpp"
43
44 #include "tcuFloat.hpp"
45 #include "tcuImageCompare.hpp"
46 #include "tcuFormatUtil.hpp"
47 #include "tcuMaybe.hpp"
48 #include "tcuResultCollector.hpp"
49 #include "tcuTestLog.hpp"
50 #include "tcuTextureUtil.hpp"
51 #include "tcuVectorUtil.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::Vec4;
65
66 using tcu::just;
67 using tcu::Maybe;
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
86 namespace renderpass
87 {
88
89 namespace
90 {
91
92 enum
93 {
94 MAX_COLOR_ATTACHMENT_COUNT = 4u
95 };
96
97 enum TestSeparateUsage
98 {
99 TEST_DEPTH = (1 << 0),
100 TEST_STENCIL = (1 << 1)
101 };
102
103 template <typename T>
safeSharedPtr(T * ptr)104 de::SharedPtr<T> safeSharedPtr(T *ptr)
105 {
106 try
107 {
108 return de::SharedPtr<T>(ptr);
109 }
110 catch (...)
111 {
112 delete ptr;
113 throw;
114 }
115 }
116
getImageAspectFlags(VkFormat vkFormat)117 VkImageAspectFlags getImageAspectFlags(VkFormat vkFormat)
118 {
119 const tcu::TextureFormat format(mapVkFormat(vkFormat));
120 const bool hasDepth(tcu::hasDepthComponent(format.order));
121 const bool hasStencil(tcu::hasStencilComponent(format.order));
122
123 if (hasDepth || hasStencil)
124 {
125 return (hasDepth ? VK_IMAGE_ASPECT_DEPTH_BIT : (VkImageAspectFlagBits)0u) |
126 (hasStencil ? VK_IMAGE_ASPECT_STENCIL_BIT : (VkImageAspectFlagBits)0u);
127 }
128 else
129 return VK_IMAGE_ASPECT_COLOR_BIT;
130 }
131
bindBufferMemory(const DeviceInterface & vk,VkDevice device,VkBuffer buffer,VkDeviceMemory mem,VkDeviceSize memOffset)132 void bindBufferMemory(const DeviceInterface &vk, VkDevice device, VkBuffer buffer, VkDeviceMemory mem,
133 VkDeviceSize memOffset)
134 {
135 VK_CHECK(vk.bindBufferMemory(device, buffer, mem, memOffset));
136 }
137
bindImageMemory(const DeviceInterface & vk,VkDevice device,VkImage image,VkDeviceMemory mem,VkDeviceSize memOffset)138 void bindImageMemory(const DeviceInterface &vk, VkDevice device, VkImage image, VkDeviceMemory mem,
139 VkDeviceSize memOffset)
140 {
141 VK_CHECK(vk.bindImageMemory(device, image, mem, memOffset));
142 }
143
createBufferMemory(const DeviceInterface & vk,VkDevice device,Allocator & allocator,VkBuffer buffer)144 de::MovePtr<Allocation> createBufferMemory(const DeviceInterface &vk, VkDevice device, Allocator &allocator,
145 VkBuffer buffer)
146 {
147 de::MovePtr<Allocation> allocation(
148 allocator.allocate(getBufferMemoryRequirements(vk, device, buffer), MemoryRequirement::HostVisible));
149 bindBufferMemory(vk, device, buffer, allocation->getMemory(), allocation->getOffset());
150 return allocation;
151 }
152
createImageMemory(const DeviceInterface & vk,VkDevice device,Allocator & allocator,VkImage image)153 de::MovePtr<Allocation> createImageMemory(const DeviceInterface &vk, VkDevice device, Allocator &allocator,
154 VkImage image)
155 {
156 de::MovePtr<Allocation> allocation(
157 allocator.allocate(getImageMemoryRequirements(vk, device, image), MemoryRequirement::Any));
158 bindImageMemory(vk, device, image, allocation->getMemory(), allocation->getOffset());
159 return allocation;
160 }
161
createImage(const DeviceInterface & vk,VkDevice device,VkImageCreateFlags flags,VkImageType imageType,VkFormat format,VkExtent3D extent,uint32_t mipLevels,uint32_t arrayLayers,VkSampleCountFlagBits samples,VkImageTiling tiling,VkImageUsageFlags usage,VkSharingMode sharingMode,uint32_t queueFamilyCount,const uint32_t * pQueueFamilyIndices,VkImageLayout initialLayout,TestSeparateUsage separateStencilUsage)162 Move<VkImage> createImage(const DeviceInterface &vk, VkDevice device, VkImageCreateFlags flags, VkImageType imageType,
163 VkFormat format, VkExtent3D extent, uint32_t mipLevels, uint32_t arrayLayers,
164 VkSampleCountFlagBits samples, VkImageTiling tiling, VkImageUsageFlags usage,
165 VkSharingMode sharingMode, uint32_t queueFamilyCount, const uint32_t *pQueueFamilyIndices,
166 VkImageLayout initialLayout, TestSeparateUsage separateStencilUsage)
167 {
168 VkImageUsageFlags depthUsage(VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
169 VkImageUsageFlags stencilUsage(VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
170 VkImageUsageFlags imageUsage(usage);
171
172 if (separateStencilUsage)
173 {
174 if (separateStencilUsage == TEST_DEPTH)
175 depthUsage = usage;
176 else // (separateStencilUsage == TEST_STENCIL)
177 stencilUsage = usage;
178
179 imageUsage = depthUsage | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
180 }
181
182 const VkImageStencilUsageCreateInfo stencilUsageInfo{VK_STRUCTURE_TYPE_IMAGE_STENCIL_USAGE_CREATE_INFO, DE_NULL,
183 stencilUsage};
184
185 const VkImageCreateInfo pCreateInfo{VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
186 separateStencilUsage ? &stencilUsageInfo : DE_NULL,
187 flags,
188 imageType,
189 format,
190 extent,
191 mipLevels,
192 arrayLayers,
193 samples,
194 tiling,
195 imageUsage,
196 sharingMode,
197 queueFamilyCount,
198 pQueueFamilyIndices,
199 initialLayout};
200
201 return createImage(vk, device, &pCreateInfo);
202 }
203
createImageView(const DeviceInterface & vk,VkDevice device,VkImageViewCreateFlags flags,VkImage image,VkImageViewType viewType,VkFormat format,VkComponentMapping components,VkImageSubresourceRange subresourceRange)204 Move<VkImageView> createImageView(const DeviceInterface &vk, VkDevice device, VkImageViewCreateFlags flags,
205 VkImage image, VkImageViewType viewType, VkFormat format,
206 VkComponentMapping components, VkImageSubresourceRange subresourceRange)
207 {
208 const VkImageViewCreateInfo pCreateInfo = {
209 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, DE_NULL, flags, image, viewType, format, components, subresourceRange,
210 };
211 return createImageView(vk, device, &pCreateInfo);
212 }
213
createImage(const InstanceInterface & vki,VkPhysicalDevice physicalDevice,const DeviceInterface & vkd,VkDevice device,VkFormat vkFormat,VkSampleCountFlagBits sampleCountBit,VkImageUsageFlags usage,uint32_t width,uint32_t height,TestSeparateUsage separateStencilUsage=(TestSeparateUsage)0u)214 Move<VkImage> createImage(const InstanceInterface &vki, VkPhysicalDevice physicalDevice, const DeviceInterface &vkd,
215 VkDevice device, VkFormat vkFormat, VkSampleCountFlagBits sampleCountBit,
216 VkImageUsageFlags usage, uint32_t width, uint32_t height,
217 TestSeparateUsage separateStencilUsage = (TestSeparateUsage)0u)
218 {
219 try
220 {
221 const tcu::TextureFormat format(mapVkFormat(vkFormat));
222 const VkImageType imageType(VK_IMAGE_TYPE_2D);
223 const VkImageTiling imageTiling(VK_IMAGE_TILING_OPTIMAL);
224 const VkFormatProperties formatProperties(getPhysicalDeviceFormatProperties(vki, physicalDevice, vkFormat));
225 const VkImageFormatProperties imageFormatProperties(
226 getPhysicalDeviceImageFormatProperties(vki, physicalDevice, vkFormat, imageType, imageTiling, usage, 0u));
227 const VkImageUsageFlags depthUsage = (separateStencilUsage == TEST_DEPTH) ?
228 usage :
229 (VkImageUsageFlags)VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
230 const VkImageUsageFlags stencilUsage = (separateStencilUsage == TEST_STENCIL) ?
231 usage :
232 (VkImageUsageFlags)VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
233 const VkExtent3D imageExtent = {width, height, 1u};
234
235 if ((tcu::hasDepthComponent(format.order) || tcu::hasStencilComponent(format.order)) &&
236 (formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) == 0)
237 TCU_THROW(NotSupportedError, "Format can't be used as depth stencil attachment");
238
239 if (!(tcu::hasDepthComponent(format.order) || tcu::hasStencilComponent(format.order)) &&
240 (formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) == 0)
241 TCU_THROW(NotSupportedError, "Format can't be used as color attachment");
242
243 if (imageFormatProperties.maxExtent.width < imageExtent.width ||
244 imageFormatProperties.maxExtent.height < imageExtent.height ||
245 ((imageFormatProperties.sampleCounts & sampleCountBit) == 0))
246 {
247 TCU_THROW(NotSupportedError, "Image type not supported");
248 }
249
250 if (separateStencilUsage)
251 {
252 const VkImageStencilUsageCreateInfo stencilUsageInfo = {
253 VK_STRUCTURE_TYPE_IMAGE_STENCIL_USAGE_CREATE_INFO, // VkStructureType sType
254 DE_NULL, // const void* pNext
255 stencilUsage // VkImageUsageFlags stencilUsage
256 };
257
258 const VkPhysicalDeviceImageFormatInfo2 formatInfo2 = {
259 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2, // VkStructureType sType
260 &stencilUsageInfo, // const void* pNext
261 vkFormat, // VkFormat format
262 imageType, // VkImageType type
263 imageTiling, // VkImageTiling tiling
264 depthUsage, // VkImageUsageFlags usage
265 (VkImageCreateFlags)0u // VkImageCreateFlags flags
266 };
267
268 VkImageFormatProperties2 extProperties = {
269 VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
270 DE_NULL,
271 {
272 {
273 0, // width
274 0, // height
275 0, // depth
276 },
277 0u, // maxMipLevels
278 0u, // maxArrayLayers
279 0, // sampleCounts
280 0u, // maxResourceSize
281 },
282 };
283
284 if ((vki.getPhysicalDeviceImageFormatProperties2(physicalDevice, &formatInfo2, &extProperties) ==
285 VK_ERROR_FORMAT_NOT_SUPPORTED) ||
286 extProperties.imageFormatProperties.maxExtent.width < imageExtent.width ||
287 extProperties.imageFormatProperties.maxExtent.height < imageExtent.height ||
288 ((extProperties.imageFormatProperties.sampleCounts & sampleCountBit) == 0))
289 {
290 TCU_THROW(NotSupportedError, "Image format not supported");
291 }
292 }
293
294 return createImage(vkd, device, 0u, imageType, vkFormat, imageExtent, 1u, 1u, sampleCountBit, imageTiling,
295 usage, VK_SHARING_MODE_EXCLUSIVE, 0u, DE_NULL, VK_IMAGE_LAYOUT_UNDEFINED,
296 separateStencilUsage);
297 }
298 catch (const vk::Error &error)
299 {
300 if (error.getError() == VK_ERROR_FORMAT_NOT_SUPPORTED)
301 TCU_THROW(NotSupportedError, "Image format not supported");
302
303 throw;
304 }
305 }
306
createImageAttachmentView(const DeviceInterface & vkd,VkDevice device,VkImage image,VkFormat format,VkImageAspectFlags aspect)307 Move<VkImageView> createImageAttachmentView(const DeviceInterface &vkd, VkDevice device, VkImage image, VkFormat format,
308 VkImageAspectFlags aspect)
309 {
310 const VkImageSubresourceRange range = {aspect, 0u, 1u, 0u, 1u};
311
312 return createImageView(vkd, device, 0u, image, VK_IMAGE_VIEW_TYPE_2D, format, makeComponentMappingRGBA(), range);
313 }
314
createSrcPrimaryInputImageView(const DeviceInterface & vkd,VkDevice device,VkImage image,VkFormat format,VkImageAspectFlags aspect,TestSeparateUsage testSeparateUsage)315 Move<VkImageView> createSrcPrimaryInputImageView(const DeviceInterface &vkd, VkDevice device, VkImage image,
316 VkFormat format, VkImageAspectFlags aspect,
317 TestSeparateUsage testSeparateUsage)
318 {
319 VkImageAspectFlags primaryDepthStencilAspect =
320 (testSeparateUsage == TEST_STENCIL) ? VK_IMAGE_ASPECT_STENCIL_BIT : VK_IMAGE_ASPECT_DEPTH_BIT;
321
322 const VkImageSubresourceRange range = {
323 aspect == (VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_DEPTH_BIT) ? primaryDepthStencilAspect : aspect, 0u,
324 1u, 0u, 1u};
325
326 return createImageView(vkd, device, 0u, image, VK_IMAGE_VIEW_TYPE_2D, format, makeComponentMappingRGBA(), range);
327 }
328
createSrcSecondaryInputImageView(const DeviceInterface & vkd,VkDevice device,VkImage image,VkFormat format,VkImageAspectFlags aspect,TestSeparateUsage separateStencilUsage)329 Move<VkImageView> createSrcSecondaryInputImageView(const DeviceInterface &vkd, VkDevice device, VkImage image,
330 VkFormat format, VkImageAspectFlags aspect,
331 TestSeparateUsage separateStencilUsage)
332 {
333 if ((aspect == (VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_DEPTH_BIT)) && !separateStencilUsage)
334 {
335 const VkImageSubresourceRange range = {VK_IMAGE_ASPECT_STENCIL_BIT, 0u, 1u, 0u, 1u};
336
337 return createImageView(vkd, device, 0u, image, VK_IMAGE_VIEW_TYPE_2D, format, makeComponentMappingRGBA(),
338 range);
339 }
340 else
341 return Move<VkImageView>();
342 }
343
getPixelSize(VkFormat vkFormat)344 VkDeviceSize getPixelSize(VkFormat vkFormat)
345 {
346 const tcu::TextureFormat format(mapVkFormat(vkFormat));
347
348 return format.getPixelSize();
349 }
350
createBuffer(const DeviceInterface & vkd,VkDevice device,VkFormat format,uint32_t width,uint32_t height)351 Move<VkBuffer> createBuffer(const DeviceInterface &vkd, VkDevice device, VkFormat format, uint32_t width,
352 uint32_t height)
353 {
354 const VkBufferUsageFlags bufferUsage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
355 const VkDeviceSize pixelSize(getPixelSize(format));
356 const VkBufferCreateInfo createInfo = {VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
357 DE_NULL,
358 0u,
359
360 width * height * pixelSize,
361 bufferUsage,
362
363 VK_SHARING_MODE_EXCLUSIVE,
364 0u,
365 DE_NULL};
366 return createBuffer(vkd, device, &createInfo);
367 }
368
sampleCountBitFromomSampleCount(uint32_t count)369 VkSampleCountFlagBits sampleCountBitFromomSampleCount(uint32_t count)
370 {
371 switch (count)
372 {
373 case 1:
374 return VK_SAMPLE_COUNT_1_BIT;
375 case 2:
376 return VK_SAMPLE_COUNT_2_BIT;
377 case 4:
378 return VK_SAMPLE_COUNT_4_BIT;
379 case 8:
380 return VK_SAMPLE_COUNT_8_BIT;
381 case 16:
382 return VK_SAMPLE_COUNT_16_BIT;
383 case 32:
384 return VK_SAMPLE_COUNT_32_BIT;
385 case 64:
386 return VK_SAMPLE_COUNT_64_BIT;
387
388 default:
389 DE_FATAL("Invalid sample count");
390 return (VkSampleCountFlagBits)(0x1u << count);
391 }
392 }
393
createMultisampleImages(const InstanceInterface & vki,VkPhysicalDevice physicalDevice,const DeviceInterface & vkd,VkDevice device,VkFormat format,uint32_t sampleCount,uint32_t width,uint32_t height)394 std::vector<VkImageSp> createMultisampleImages(const InstanceInterface &vki, VkPhysicalDevice physicalDevice,
395 const DeviceInterface &vkd, VkDevice device, VkFormat format,
396 uint32_t sampleCount, uint32_t width, uint32_t height)
397 {
398 std::vector<VkImageSp> images(sampleCount);
399
400 for (size_t imageNdx = 0; imageNdx < images.size(); imageNdx++)
401 images[imageNdx] = safeSharedPtr(new vk::Unique<VkImage>(
402 createImage(vki, physicalDevice, vkd, device, format, sampleCountBitFromomSampleCount(sampleCount),
403 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, width, height)));
404
405 return images;
406 }
407
createSingleSampleImages(const InstanceInterface & vki,VkPhysicalDevice physicalDevice,const DeviceInterface & vkd,VkDevice device,VkFormat format,uint32_t sampleCount,uint32_t width,uint32_t height)408 std::vector<VkImageSp> createSingleSampleImages(const InstanceInterface &vki, VkPhysicalDevice physicalDevice,
409 const DeviceInterface &vkd, VkDevice device, VkFormat format,
410 uint32_t sampleCount, uint32_t width, uint32_t height)
411 {
412 std::vector<VkImageSp> images(sampleCount);
413
414 for (size_t imageNdx = 0; imageNdx < images.size(); imageNdx++)
415 images[imageNdx] = safeSharedPtr(new vk::Unique<VkImage>(
416 createImage(vki, physicalDevice, vkd, device, format, VK_SAMPLE_COUNT_1_BIT,
417 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, width, height)));
418
419 return images;
420 }
421
createImageMemory(const DeviceInterface & vkd,VkDevice device,Allocator & allocator,const std::vector<VkImageSp> images)422 std::vector<de::SharedPtr<Allocation>> createImageMemory(const DeviceInterface &vkd, VkDevice device,
423 Allocator &allocator, const std::vector<VkImageSp> images)
424 {
425 std::vector<de::SharedPtr<Allocation>> memory(images.size());
426
427 for (size_t memoryNdx = 0; memoryNdx < memory.size(); memoryNdx++)
428 memory[memoryNdx] = safeSharedPtr(createImageMemory(vkd, device, allocator, **images[memoryNdx]).release());
429
430 return memory;
431 }
432
createImageAttachmentViews(const DeviceInterface & vkd,VkDevice device,const std::vector<VkImageSp> & images,VkFormat format,VkImageAspectFlagBits aspect)433 std::vector<VkImageViewSp> createImageAttachmentViews(const DeviceInterface &vkd, VkDevice device,
434 const std::vector<VkImageSp> &images, VkFormat format,
435 VkImageAspectFlagBits aspect)
436 {
437 std::vector<VkImageViewSp> views(images.size());
438
439 for (size_t imageNdx = 0; imageNdx < images.size(); imageNdx++)
440 views[imageNdx] = safeSharedPtr(
441 new vk::Unique<VkImageView>(createImageAttachmentView(vkd, device, **images[imageNdx], format, aspect)));
442
443 return views;
444 }
445
createBuffers(const DeviceInterface & vkd,VkDevice device,VkFormat format,uint32_t sampleCount,uint32_t width,uint32_t height)446 std::vector<VkBufferSp> createBuffers(const DeviceInterface &vkd, VkDevice device, VkFormat format,
447 uint32_t sampleCount, uint32_t width, uint32_t height)
448 {
449 std::vector<VkBufferSp> buffers(sampleCount);
450
451 for (size_t bufferNdx = 0; bufferNdx < buffers.size(); bufferNdx++)
452 buffers[bufferNdx] = safeSharedPtr(new vk::Unique<VkBuffer>(createBuffer(vkd, device, format, width, height)));
453
454 return buffers;
455 }
456
createBufferMemory(const DeviceInterface & vkd,VkDevice device,Allocator & allocator,const std::vector<VkBufferSp> buffers)457 std::vector<de::SharedPtr<Allocation>> createBufferMemory(const DeviceInterface &vkd, VkDevice device,
458 Allocator &allocator, const std::vector<VkBufferSp> buffers)
459 {
460 std::vector<de::SharedPtr<Allocation>> memory(buffers.size());
461
462 for (size_t memoryNdx = 0; memoryNdx < memory.size(); memoryNdx++)
463 memory[memoryNdx] = safeSharedPtr(createBufferMemory(vkd, device, allocator, **buffers[memoryNdx]).release());
464
465 return memory;
466 }
467
468 template <typename AttachmentDesc, typename AttachmentRef, typename SubpassDesc, typename SubpassDep,
469 typename RenderPassCreateInfo>
createRenderPass(const DeviceInterface & vkd,VkDevice device,VkFormat srcFormat,VkFormat dstFormat,uint32_t sampleCount,RenderingType renderingType,TestSeparateUsage separateStencilUsage)470 Move<VkRenderPass> createRenderPass(const DeviceInterface &vkd, VkDevice device, VkFormat srcFormat, VkFormat dstFormat,
471 uint32_t sampleCount, RenderingType renderingType,
472 TestSeparateUsage separateStencilUsage)
473 {
474 const VkSampleCountFlagBits samples(sampleCountBitFromomSampleCount(sampleCount));
475 const uint32_t splitSubpassCount(deDivRoundUp32(sampleCount, MAX_COLOR_ATTACHMENT_COUNT));
476 const tcu::TextureFormat format(mapVkFormat(srcFormat));
477 const bool isDepthStencilFormat(tcu::hasDepthComponent(format.order) || tcu::hasStencilComponent(format.order));
478 const VkImageAspectFlags inputAspect(
479 separateStencilUsage == TEST_DEPTH ? (VkImageAspectFlags)VK_IMAGE_ASPECT_DEPTH_BIT :
480 separateStencilUsage == TEST_STENCIL ? (VkImageAspectFlags)VK_IMAGE_ASPECT_STENCIL_BIT :
481 getImageAspectFlags(srcFormat));
482 vector<SubpassDesc> subpasses;
483 vector<vector<AttachmentRef>> dstAttachmentRefs(splitSubpassCount);
484 vector<vector<AttachmentRef>> dstResolveAttachmentRefs(splitSubpassCount);
485 vector<AttachmentDesc> attachments;
486 vector<SubpassDep> dependencies;
487 const AttachmentRef
488 srcAttachmentRef // VkAttachmentReference || VkAttachmentReference2KHR
489 (
490 // || VkStructureType sType;
491 DE_NULL, // || const void* pNext;
492 0u, // uint32_t attachment; || uint32_t attachment;
493 isDepthStencilFormat // VkImageLayout layout; || VkImageLayout layout;
494 ?
495 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL :
496 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
497 0u // || VkImageAspectFlags aspectMask;
498 );
499 const AttachmentRef
500 srcAttachmentInputRef // VkAttachmentReference || VkAttachmentReference2KHR
501 (
502 // || VkStructureType sType;
503 DE_NULL, // || const void* pNext;
504 0u, // uint32_t attachment; || uint32_t attachment;
505 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // VkImageLayout layout; || VkImageLayout layout;
506 (renderingType == RENDERING_TYPE_RENDERPASS2) // || VkImageAspectFlags aspectMask;
507 ?
508 inputAspect :
509 0u);
510
511 {
512 const AttachmentDesc
513 srcAttachment // VkAttachmentDescription || VkAttachmentDescription2KHR
514 (
515 // || VkStructureType sType;
516 DE_NULL, // || const void* pNext;
517 0u, // VkAttachmentDescriptionFlags flags; || VkAttachmentDescriptionFlags flags;
518 srcFormat, // VkFormat format; || VkFormat format;
519 samples, // VkSampleCountFlagBits samples; || VkSampleCountFlagBits samples;
520 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp loadOp; || VkAttachmentLoadOp loadOp;
521 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp storeOp; || VkAttachmentStoreOp storeOp;
522 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; || VkAttachmentLoadOp stencilLoadOp;
523 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; || VkAttachmentStoreOp stencilStoreOp;
524 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; || VkImageLayout initialLayout;
525 VK_IMAGE_LAYOUT_GENERAL // VkImageLayout finalLayout; || VkImageLayout finalLayout;
526 );
527
528 attachments.push_back(srcAttachment);
529 }
530
531 for (uint32_t splitSubpassIndex = 0; splitSubpassIndex < splitSubpassCount; splitSubpassIndex++)
532 {
533 for (uint32_t sampleNdx = 0; sampleNdx < de::min((uint32_t)MAX_COLOR_ATTACHMENT_COUNT,
534 sampleCount - splitSubpassIndex * MAX_COLOR_ATTACHMENT_COUNT);
535 sampleNdx++)
536 {
537 // Multisample color attachment
538 {
539 const AttachmentDesc
540 dstAttachment // VkAttachmentDescription || VkAttachmentDescription2KHR
541 (
542 // || VkStructureType sType;
543 DE_NULL, // || const void* pNext;
544 0u, // VkAttachmentDescriptionFlags flags; || VkAttachmentDescriptionFlags flags;
545 dstFormat, // VkFormat format; || VkFormat format;
546 samples, // VkSampleCountFlagBits samples; || VkSampleCountFlagBits samples;
547 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp loadOp; || VkAttachmentLoadOp loadOp;
548 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp storeOp; || VkAttachmentStoreOp storeOp;
549 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; || VkAttachmentLoadOp stencilLoadOp;
550 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; || VkAttachmentStoreOp stencilStoreOp;
551 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; || VkImageLayout initialLayout;
552 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout; || VkImageLayout finalLayout;
553 );
554 const AttachmentRef
555 dstAttachmentRef // VkAttachmentReference || VkAttachmentReference2KHR
556 (
557 // || VkStructureType sType;
558 DE_NULL, // || const void* pNext;
559 (uint32_t)attachments.size(), // uint32_t attachment; || uint32_t attachment;
560 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout layout; || VkImageLayout layout;
561 0u // || VkImageAspectFlags aspectMask;
562 );
563
564 attachments.push_back(dstAttachment);
565 dstAttachmentRefs[splitSubpassIndex].push_back(dstAttachmentRef);
566 }
567 // Resolve attachment
568 {
569 const AttachmentDesc
570 dstAttachment // VkAttachmentDescription || VkAttachmentDescription2KHR
571 (
572 // || VkStructureType sType;
573 DE_NULL, // || const void* pNext;
574 0u, // VkAttachmentDescriptionFlags flags; || VkAttachmentDescriptionFlags flags;
575 dstFormat, // VkFormat format; || VkFormat format;
576 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; || VkSampleCountFlagBits samples;
577 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp loadOp; || VkAttachmentLoadOp loadOp;
578 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp; || VkAttachmentStoreOp storeOp;
579 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; || VkAttachmentLoadOp stencilLoadOp;
580 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp stencilStoreOp; || VkAttachmentStoreOp stencilStoreOp;
581 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; || VkImageLayout initialLayout;
582 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL // VkImageLayout finalLayout; || VkImageLayout finalLayout;
583 );
584 const AttachmentRef
585 dstAttachmentRef // VkAttachmentReference || VkAttachmentReference2KHR
586 (
587 // || VkStructureType sType;
588 DE_NULL, // || const void* pNext;
589 (uint32_t)attachments.size(), // uint32_t attachment; || uint32_t attachment;
590 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout layout; || VkImageLayout layout;
591 0u // || VkImageAspectFlags aspectMask;
592 );
593
594 attachments.push_back(dstAttachment);
595 dstResolveAttachmentRefs[splitSubpassIndex].push_back(dstAttachmentRef);
596 }
597 }
598 }
599
600 {
601 {
602 const SubpassDesc
603 subpass // VkSubpassDescription || VkSubpassDescription2KHR
604 (
605 // || VkStructureType sType;
606 DE_NULL, // || const void* pNext;
607 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags; || VkSubpassDescriptionFlags flags;
608 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint; || VkPipelineBindPoint pipelineBindPoint;
609 0u, // || uint32_t viewMask;
610 0u, // uint32_t inputAttachmentCount; || uint32_t inputAttachmentCount;
611 DE_NULL, // const VkAttachmentReference* pInputAttachments; || const VkAttachmentReference2KHR* pInputAttachments;
612 isDepthStencilFormat ? 0u :
613 1u, // uint32_t colorAttachmentCount; || uint32_t colorAttachmentCount;
614 isDepthStencilFormat ?
615 DE_NULL :
616 &srcAttachmentRef, // const VkAttachmentReference* pColorAttachments; || const VkAttachmentReference2KHR* pColorAttachments;
617 DE_NULL, // const VkAttachmentReference* pResolveAttachments; || const VkAttachmentReference2KHR* pResolveAttachments;
618 isDepthStencilFormat ?
619 &srcAttachmentRef :
620 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment; || const VkAttachmentReference2KHR* pDepthStencilAttachment;
621 0u, // uint32_t preserveAttachmentCount; || uint32_t preserveAttachmentCount;
622 DE_NULL // const uint32_t* pPreserveAttachments; || const uint32_t* pPreserveAttachments;
623 );
624
625 subpasses.push_back(subpass);
626 }
627
628 for (uint32_t splitSubpassIndex = 0; splitSubpassIndex < splitSubpassCount; splitSubpassIndex++)
629 {
630 {
631 const SubpassDesc
632 subpass // VkSubpassDescription || VkSubpassDescription2KHR
633 (
634 // || VkStructureType sType;
635 DE_NULL, // || const void* pNext;
636 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags; || VkSubpassDescriptionFlags flags;
637 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint; || VkPipelineBindPoint pipelineBindPoint;
638 0u, // || uint32_t viewMask;
639 1u, // uint32_t inputAttachmentCount; || uint32_t inputAttachmentCount;
640 &srcAttachmentInputRef, // const VkAttachmentReference* pInputAttachments; || const VkAttachmentReference2KHR* pInputAttachments;
641 (uint32_t)dstAttachmentRefs[splitSubpassIndex]
642 .size(), // uint32_t colorAttachmentCount; || uint32_t colorAttachmentCount;
643 &dstAttachmentRefs
644 [splitSubpassIndex]
645 [0], // const VkAttachmentReference* pColorAttachments; || const VkAttachmentReference2KHR* pColorAttachments;
646 &dstResolveAttachmentRefs
647 [splitSubpassIndex]
648 [0], // const VkAttachmentReference* pResolveAttachments; || const VkAttachmentReference2KHR* pResolveAttachments;
649 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment; || const VkAttachmentReference2KHR* pDepthStencilAttachment;
650 0u, // uint32_t preserveAttachmentCount; || uint32_t preserveAttachmentCount;
651 DE_NULL // const uint32_t* pPreserveAttachments; || const uint32_t* pPreserveAttachments;
652 );
653 subpasses.push_back(subpass);
654 }
655 {
656 const SubpassDep
657 dependency // VkSubpassDependency || VkSubpassDependency2KHR
658 (
659 // || VkStructureType sType;
660 DE_NULL, // || const void* pNext;
661 0u, // uint32_t srcSubpass; || uint32_t srcSubpass;
662 splitSubpassIndex + 1, // uint32_t dstSubpass; || uint32_t dstSubpass;
663 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
664 VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, // VkPipelineStageFlags srcStageMask; || VkPipelineStageFlags srcStageMask;
665 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, // VkPipelineStageFlags dstStageMask; || VkPipelineStageFlags dstStageMask;
666 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
667 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask; || VkAccessFlags srcAccessMask;
668 VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, // VkAccessFlags dstAccessMask; || VkAccessFlags dstAccessMask;
669 VK_DEPENDENCY_BY_REGION_BIT, // VkDependencyFlags dependencyFlags; || VkDependencyFlags dependencyFlags;
670 0u // || int32_t viewOffset;
671 );
672
673 dependencies.push_back(dependency);
674 }
675 }
676 // the last subpass must synchronize with all prior subpasses
677 for (uint32_t splitSubpassIndex = 0; splitSubpassIndex < (splitSubpassCount - 1); splitSubpassIndex++)
678 {
679 const SubpassDep dependency // VkSubpassDependency || VkSubpassDependency2KHR
680 (
681 // || VkStructureType sType;
682 DE_NULL, // || const void* pNext;
683 splitSubpassIndex + 1, // uint32_t srcSubpass; || uint32_t srcSubpass;
684 splitSubpassCount, // uint32_t dstSubpass; || uint32_t dstSubpass;
685 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
686 VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, // VkPipelineStageFlags srcStageMask; || VkPipelineStageFlags srcStageMask;
687 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, // VkPipelineStageFlags dstStageMask; || VkPipelineStageFlags dstStageMask;
688 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
689 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask; || VkAccessFlags srcAccessMask;
690 VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, // VkAccessFlags dstAccessMask; || VkAccessFlags dstAccessMask;
691 VK_DEPENDENCY_BY_REGION_BIT, // VkDependencyFlags dependencyFlags; || VkDependencyFlags dependencyFlags;
692 0u // || int32_t viewOffset;
693 );
694 dependencies.push_back(dependency);
695 }
696 const RenderPassCreateInfo
697 renderPassCreator // VkRenderPassCreateInfo || VkRenderPassCreateInfo2KHR
698 (
699 // VkStructureType sType; || VkStructureType sType;
700 DE_NULL, // const void* pNext; || const void* pNext;
701 (VkRenderPassCreateFlags)0u, // VkRenderPassCreateFlags flags; || VkRenderPassCreateFlags flags;
702 (uint32_t)attachments.size(), // uint32_t attachmentCount; || uint32_t attachmentCount;
703 &attachments
704 [0], // const VkAttachmentDescription* pAttachments; || const VkAttachmentDescription2KHR* pAttachments;
705 (uint32_t)subpasses.size(), // uint32_t subpassCount; || uint32_t subpassCount;
706 &subpasses
707 [0], // const VkSubpassDescription* pSubpasses; || const VkSubpassDescription2KHR* pSubpasses;
708 (uint32_t)dependencies.size(), // uint32_t dependencyCount; || uint32_t dependencyCount;
709 &dependencies
710 [0], // const VkSubpassDependency* pDependencies; || const VkSubpassDependency2KHR* pDependencies;
711 0u, // || uint32_t correlatedViewMaskCount;
712 DE_NULL // || const uint32_t* pCorrelatedViewMasks;
713 );
714
715 return renderPassCreator.createRenderPass(vkd, device);
716 }
717 }
718
createRenderPass(const DeviceInterface & vkd,VkDevice device,VkFormat srcFormat,VkFormat dstFormat,uint32_t sampleCount,const RenderingType renderingType,const TestSeparateUsage separateStencilUsage)719 Move<VkRenderPass> createRenderPass(const DeviceInterface &vkd, VkDevice device, VkFormat srcFormat, VkFormat dstFormat,
720 uint32_t sampleCount, const RenderingType renderingType,
721 const TestSeparateUsage separateStencilUsage)
722 {
723 switch (renderingType)
724 {
725 case RENDERING_TYPE_RENDERPASS_LEGACY:
726 return createRenderPass<AttachmentDescription1, AttachmentReference1, SubpassDescription1, SubpassDependency1,
727 RenderPassCreateInfo1>(vkd, device, srcFormat, dstFormat, sampleCount, renderingType,
728 separateStencilUsage);
729 case RENDERING_TYPE_RENDERPASS2:
730 return createRenderPass<AttachmentDescription2, AttachmentReference2, SubpassDescription2, SubpassDependency2,
731 RenderPassCreateInfo2>(vkd, device, srcFormat, dstFormat, sampleCount, renderingType,
732 separateStencilUsage);
733 case RENDERING_TYPE_DYNAMIC_RENDERING:
734 return Move<VkRenderPass>();
735 default:
736 TCU_THROW(InternalError, "Impossible");
737 }
738 }
739
createFramebuffer(const DeviceInterface & vkd,VkDevice device,VkRenderPass renderPass,VkImageView srcImageView,const std::vector<VkImageViewSp> & dstMultisampleImageViews,const std::vector<VkImageViewSp> & dstSinglesampleImageViews,uint32_t width,uint32_t height)740 Move<VkFramebuffer> createFramebuffer(const DeviceInterface &vkd, VkDevice device, VkRenderPass renderPass,
741 VkImageView srcImageView,
742 const std::vector<VkImageViewSp> &dstMultisampleImageViews,
743 const std::vector<VkImageViewSp> &dstSinglesampleImageViews, uint32_t width,
744 uint32_t height)
745 {
746 // when RenderPass was not created then we are testing dynamic rendering
747 // and we can't create framebuffer without valid RenderPass object
748 if (!renderPass)
749 return Move<VkFramebuffer>();
750
751 std::vector<VkImageView> attachments;
752
753 attachments.reserve(dstMultisampleImageViews.size() + dstSinglesampleImageViews.size() + 1u);
754
755 attachments.push_back(srcImageView);
756
757 DE_ASSERT(dstMultisampleImageViews.size() == dstSinglesampleImageViews.size());
758
759 for (size_t ndx = 0; ndx < dstMultisampleImageViews.size(); ndx++)
760 {
761 attachments.push_back(**dstMultisampleImageViews[ndx]);
762 attachments.push_back(**dstSinglesampleImageViews[ndx]);
763 }
764
765 const VkFramebufferCreateInfo createInfo = {VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
766 DE_NULL,
767 0u,
768
769 renderPass,
770 (uint32_t)attachments.size(),
771 &attachments[0],
772
773 width,
774 height,
775 1u};
776
777 return createFramebuffer(vkd, device, &createInfo);
778 }
779
createSplitDescriptorSetLayout(const DeviceInterface & vkd,VkDevice device,VkFormat vkFormat)780 Move<VkDescriptorSetLayout> createSplitDescriptorSetLayout(const DeviceInterface &vkd, VkDevice device,
781 VkFormat vkFormat)
782 {
783 const tcu::TextureFormat format(mapVkFormat(vkFormat));
784 const bool hasDepth(tcu::hasDepthComponent(format.order));
785 const bool hasStencil(tcu::hasStencilComponent(format.order));
786 const VkDescriptorSetLayoutBinding bindings[] = {
787 {0u, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1u, VK_SHADER_STAGE_FRAGMENT_BIT, DE_NULL},
788 {1u, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1u, VK_SHADER_STAGE_FRAGMENT_BIT, DE_NULL}};
789 const VkDescriptorSetLayoutCreateInfo createInfo = {VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, DE_NULL,
790 0u,
791
792 hasDepth && hasStencil ? 2u : 1u, bindings};
793
794 return createDescriptorSetLayout(vkd, device, &createInfo);
795 }
796
797 #ifndef CTS_USES_VULKANSC
getRenderingAttachmentLocationInfo(std::vector<uint32_t> & colorAttachmentLocations,bool isDepthStencilFormat,uint32_t sampleCount,uint32_t subpassIndex)798 VkRenderingAttachmentLocationInfoKHR getRenderingAttachmentLocationInfo(std::vector<uint32_t> &colorAttachmentLocations,
799 bool isDepthStencilFormat, uint32_t sampleCount,
800 uint32_t subpassIndex)
801 {
802 const uint32_t colorAttachmentCount(
803 de::min((uint32_t)MAX_COLOR_ATTACHMENT_COUNT, sampleCount - subpassIndex * MAX_COLOR_ATTACHMENT_COUNT));
804 const uint32_t firstAttachment(subpassIndex * colorAttachmentCount + !isDepthStencilFormat);
805
806 DE_ASSERT(firstAttachment + colorAttachmentCount <= colorAttachmentLocations.size());
807
808 std::fill(colorAttachmentLocations.begin(), colorAttachmentLocations.end(), VK_ATTACHMENT_UNUSED);
809 for (uint32_t i = 0; i < colorAttachmentCount; ++i)
810 colorAttachmentLocations[firstAttachment + i] = i;
811
812 return {
813 VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_LOCATION_INFO_KHR, DE_NULL,
814 (uint32_t)colorAttachmentLocations.size(), // uint32_t colorAttachmentCount
815 colorAttachmentLocations.data(), // const uint32_t* pColorAttachmentLocations
816 };
817 }
818
getRenderingInputAttachmentIndexInfo(std::vector<uint32_t> & colorAttachmentInputIndices,uint32_t & depthAttachmentInputIndex,uint32_t & stencilAttachmentInputIndex,bool isDepthFormat,bool isStencilFormat,void * pNext=DE_NULL)819 VkRenderingInputAttachmentIndexInfoKHR getRenderingInputAttachmentIndexInfo(
820 std::vector<uint32_t> &colorAttachmentInputIndices, uint32_t &depthAttachmentInputIndex,
821 uint32_t &stencilAttachmentInputIndex, bool isDepthFormat, bool isStencilFormat, void *pNext = DE_NULL)
822 {
823 depthAttachmentInputIndex = 0u;
824 stencilAttachmentInputIndex = 0u;
825
826 std::fill(colorAttachmentInputIndices.begin(), colorAttachmentInputIndices.end(), VK_ATTACHMENT_UNUSED);
827 if (!isDepthFormat && !isStencilFormat)
828 colorAttachmentInputIndices[0] = 0;
829
830 return {
831 VK_STRUCTURE_TYPE_RENDERING_INPUT_ATTACHMENT_INDEX_INFO_KHR,
832 pNext,
833 (uint32_t)colorAttachmentInputIndices.size(), // uint32_t colorAttachmentCount
834 colorAttachmentInputIndices.data(), // const uint32_t* pColorAttachmentInputIndices
835 (isDepthFormat ? &depthAttachmentInputIndex : DE_NULL), // uint32_t* pDepthInputAttachmentIndex
836 (isStencilFormat ? &stencilAttachmentInputIndex : DE_NULL), // uint32_t* pStencilInputAttachmentIndex
837 };
838 }
839 #endif
840
createSplitDescriptorPool(const DeviceInterface & vkd,VkDevice device)841 Move<VkDescriptorPool> createSplitDescriptorPool(const DeviceInterface &vkd, VkDevice device)
842 {
843 const VkDescriptorPoolSize size = {VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 2u};
844 const VkDescriptorPoolCreateInfo createInfo = {VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
845 DE_NULL,
846 VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
847 2u,
848 1u,
849 &size};
850
851 return createDescriptorPool(vkd, device, &createInfo);
852 }
853
createSplitDescriptorSet(const DeviceInterface & vkd,VkDevice device,VkDescriptorPool pool,VkDescriptorSetLayout layout,VkRenderPass renderPass,VkImageView primaryImageView,VkImageView secondaryImageView,VkImageLayout imageReadLayout)854 Move<VkDescriptorSet> createSplitDescriptorSet(const DeviceInterface &vkd, VkDevice device, VkDescriptorPool pool,
855 VkDescriptorSetLayout layout, VkRenderPass renderPass,
856 VkImageView primaryImageView, VkImageView secondaryImageView,
857 VkImageLayout imageReadLayout)
858 {
859 DE_UNREF(renderPass);
860
861 const VkDescriptorSetAllocateInfo allocateInfo = {VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, DE_NULL,
862
863 pool, 1u, &layout};
864 Move<VkDescriptorSet> set(allocateDescriptorSet(vkd, device, &allocateInfo));
865
866 {
867 const VkDescriptorImageInfo imageInfos[] = {{(VkSampler)0u, primaryImageView, imageReadLayout},
868 {(VkSampler)0u, secondaryImageView, imageReadLayout}};
869 const VkWriteDescriptorSet writes[] = {
870 {VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, DE_NULL,
871
872 *set, 0u, 0u, 1u, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, &imageInfos[0], DE_NULL, DE_NULL},
873 {VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, DE_NULL,
874
875 *set, 1u, 0u, 1u, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, &imageInfos[1], DE_NULL, DE_NULL}};
876 const uint32_t count = secondaryImageView != (VkImageView)0 ? 2u : 1u;
877
878 vkd.updateDescriptorSets(device, count, writes, 0u, DE_NULL);
879 }
880 return set;
881 }
882
883 struct TestConfig
884 {
TestConfigvkt::renderpass::__anon7a6d0e070111::TestConfig885 TestConfig(VkFormat format_, uint32_t sampleCount_, SharedGroupParams groupParams_,
886 TestSeparateUsage separateStencilUsage_ = (TestSeparateUsage)0u)
887 : format(format_)
888 , sampleCount(sampleCount_)
889 , groupParams(groupParams_)
890 , separateStencilUsage(separateStencilUsage_)
891 {
892 }
893
894 VkFormat format;
895 uint32_t sampleCount;
896 SharedGroupParams groupParams;
897 TestSeparateUsage separateStencilUsage;
898 };
899
getSrcImageUsage(VkFormat vkFormat)900 VkImageUsageFlags getSrcImageUsage(VkFormat vkFormat)
901 {
902 const tcu::TextureFormat format(mapVkFormat(vkFormat));
903 const bool hasDepth(tcu::hasDepthComponent(format.order));
904 const bool hasStencil(tcu::hasStencilComponent(format.order));
905
906 if (hasDepth || hasStencil)
907 return VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
908 else
909 return VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
910 }
911
getDstFormat(VkFormat vkFormat,TestSeparateUsage separateStencilUsage)912 VkFormat getDstFormat(VkFormat vkFormat, TestSeparateUsage separateStencilUsage)
913 {
914 const tcu::TextureFormat format(mapVkFormat(vkFormat));
915 const bool hasDepth(tcu::hasDepthComponent(format.order));
916 const bool hasStencil(tcu::hasStencilComponent(format.order));
917
918 if (hasDepth && hasStencil && !separateStencilUsage)
919 return VK_FORMAT_R32G32_SFLOAT;
920 else if (hasDepth || hasStencil)
921 return VK_FORMAT_R32_SFLOAT;
922 else
923 return vkFormat;
924 }
925
chooseSrcInputImageLayout(const SharedGroupParams groupParams)926 VkImageLayout chooseSrcInputImageLayout(const SharedGroupParams groupParams)
927 {
928 #ifndef CTS_USES_VULKANSC
929 if (groupParams->renderingType == RENDERING_TYPE_DYNAMIC_RENDERING)
930 {
931 // use general layout for local reads for some tests
932 if (groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
933 return VK_IMAGE_LAYOUT_GENERAL;
934 return VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ_KHR;
935 }
936 #else
937 DE_UNREF(groupParams);
938 #endif // CTS_USES_VULKANSC
939
940 return VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
941 }
942
943 #ifndef CTS_USES_VULKANSC
beginSecondaryCmdBuffer(const DeviceInterface & vk,VkCommandBuffer secCmdBuffer,VkFormat srcFormat,VkFormat dstFormat,uint32_t colorAttachmentCount,uint32_t sampleCount)944 void beginSecondaryCmdBuffer(const DeviceInterface &vk, VkCommandBuffer secCmdBuffer, VkFormat srcFormat,
945 VkFormat dstFormat, uint32_t colorAttachmentCount, uint32_t sampleCount)
946 {
947 VkCommandBufferUsageFlags usageFlags(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
948 const tcu::TextureFormat format(mapVkFormat(srcFormat));
949 const bool isDepthFormat(tcu::hasDepthComponent(format.order));
950 const bool isStencilFormat(tcu::hasStencilComponent(format.order));
951 std::vector<VkFormat> colorAttachmentFormats(colorAttachmentCount, dstFormat);
952
953 const VkCommandBufferInheritanceRenderingInfoKHR inheritanceRenderingInfo{
954 VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR, // VkStructureType sType;
955 DE_NULL, // const void* pNext;
956 0u, // VkRenderingFlagsKHR flags;
957 0u, // uint32_t viewMask;
958 colorAttachmentCount, // uint32_t colorAttachmentCount;
959 colorAttachmentFormats.data(), // const VkFormat* pColorAttachmentFormats;
960 isDepthFormat ? srcFormat : VK_FORMAT_UNDEFINED, // VkFormat depthAttachmentFormat;
961 isStencilFormat ? srcFormat : VK_FORMAT_UNDEFINED, // VkFormat stencilAttachmentFormat;
962 sampleCountBitFromomSampleCount(sampleCount), // VkSampleCountFlagBits rasterizationSamples;
963 };
964 const VkCommandBufferInheritanceInfo bufferInheritanceInfo{
965 VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, // VkStructureType sType;
966 &inheritanceRenderingInfo, // const void* pNext;
967 DE_NULL, // VkRenderPass renderPass;
968 0u, // uint32_t subpass;
969 DE_NULL, // VkFramebuffer framebuffer;
970 VK_FALSE, // VkBool32 occlusionQueryEnable;
971 (VkQueryControlFlags)0u, // VkQueryControlFlags queryFlags;
972 (VkQueryPipelineStatisticFlags)0u // VkQueryPipelineStatisticFlags pipelineStatistics;
973 };
974 const VkCommandBufferBeginInfo commandBufBeginParams{
975 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
976 DE_NULL, // const void* pNext;
977 usageFlags, // VkCommandBufferUsageFlags flags;
978 &bufferInheritanceInfo // const VkCommandBufferInheritanceInfo* pInheritanceInfo;
979 };
980 VK_CHECK(vk.beginCommandBuffer(secCmdBuffer, &commandBufBeginParams));
981 }
982 #endif // CTS_USES_VULKANSC
983
984 class MultisampleRenderPassTestInstance : public TestInstance
985 {
986 public:
987 MultisampleRenderPassTestInstance(Context &context, TestConfig config);
988 ~MultisampleRenderPassTestInstance(void) = default;
989
990 tcu::TestStatus iterate(void);
991
992 protected:
993 void createRenderPipeline(void);
994 void createSplitPipelines(void);
995
996 template <typename RenderpassSubpass>
997 tcu::TestStatus iterateInternal(void);
998 tcu::TestStatus iterateInternalDynamicRendering(void);
999 #ifndef CTS_USES_VULKANSC
1000 void preRenderCommands(const DeviceInterface &vk, VkCommandBuffer cmdBuffer, VkImageAspectFlags aspectMask);
1001 void inbetweenRenderCommands(const DeviceInterface &vk, VkCommandBuffer cmdBuffer, VkImageAspectFlags aspectMask);
1002 #endif // CTS_USES_VULKANSC
1003 void drawFirstSubpass(const DeviceInterface &vk, VkCommandBuffer cmdBuffer);
1004 void drawNextSubpass(const DeviceInterface &vk, VkCommandBuffer cmdBuffer, uint32_t splitPipelineNdx);
1005 void postRenderCommands(const DeviceInterface &vk, VkCommandBuffer cmdBuffer);
1006
1007 tcu::TestStatus verifyResult(void);
1008
1009 private:
1010 const SharedGroupParams m_groupParams;
1011 const TestSeparateUsage m_separateStencilUsage;
1012
1013 const VkFormat m_srcFormat;
1014 const VkFormat m_dstFormat;
1015 const uint32_t m_sampleCount;
1016 const uint32_t m_width;
1017 const uint32_t m_height;
1018 const VkPushConstantRange m_pushConstantRange;
1019
1020 const VkImageAspectFlags m_srcImageAspect;
1021 const VkImageUsageFlags m_srcImageUsage;
1022 const Unique<VkImage> m_srcImage;
1023 const de::UniquePtr<Allocation> m_srcImageMemory;
1024 const Unique<VkImageView> m_srcImageView;
1025 const Unique<VkImageView> m_srcPrimaryInputImageView;
1026 const Unique<VkImageView> m_srcSecondaryInputImageView;
1027 const VkImageLayout m_srcInputImageReadLayout;
1028
1029 const std::vector<VkImageSp> m_dstMultisampleImages;
1030 const std::vector<de::SharedPtr<Allocation>> m_dstMultisampleImageMemory;
1031 const std::vector<VkImageViewSp> m_dstMultisampleImageViews;
1032
1033 const std::vector<VkImageSp> m_dstSinglesampleImages;
1034 const std::vector<de::SharedPtr<Allocation>> m_dstSinglesampleImageMemory;
1035 const std::vector<VkImageViewSp> m_dstSinglesampleImageViews;
1036
1037 const std::vector<VkBufferSp> m_dstBuffers;
1038 const std::vector<de::SharedPtr<Allocation>> m_dstBufferMemory;
1039
1040 const Unique<VkRenderPass> m_renderPass;
1041 const Unique<VkFramebuffer> m_framebuffer;
1042
1043 const PipelineLayoutWrapper m_renderPipelineLayout;
1044 GraphicsPipelineWrapper m_renderPipeline;
1045
1046 const Unique<VkDescriptorSetLayout> m_splitDescriptorSetLayout;
1047 const PipelineLayoutWrapper m_splitPipelineLayout;
1048 std::vector<GraphicsPipelineWrapper> m_splitPipelines;
1049 const Unique<VkDescriptorPool> m_splitDescriptorPool;
1050 const Unique<VkDescriptorSet> m_splitDescriptorSet;
1051
1052 const Unique<VkCommandPool> m_commandPool;
1053 tcu::ResultCollector m_resultCollector;
1054 };
1055
MultisampleRenderPassTestInstance(Context & context,TestConfig config)1056 MultisampleRenderPassTestInstance::MultisampleRenderPassTestInstance(Context &context, TestConfig config)
1057 : TestInstance(context)
1058 , m_groupParams(config.groupParams)
1059 , m_separateStencilUsage(config.separateStencilUsage)
1060 , m_srcFormat(config.format)
1061 , m_dstFormat(getDstFormat(config.format, config.separateStencilUsage))
1062 , m_sampleCount(config.sampleCount)
1063 , m_width(32u)
1064 , m_height(32u)
1065 , m_pushConstantRange{VK_SHADER_STAGE_FRAGMENT_BIT, 0u, 4u}
1066
1067 , m_srcImageAspect(getImageAspectFlags(m_srcFormat))
1068 , m_srcImageUsage(getSrcImageUsage(m_srcFormat))
1069 , m_srcImage(createImage(context.getInstanceInterface(), context.getPhysicalDevice(), context.getDeviceInterface(),
1070 context.getDevice(), m_srcFormat, sampleCountBitFromomSampleCount(m_sampleCount),
1071 m_srcImageUsage, m_width, m_height, m_separateStencilUsage))
1072 , m_srcImageMemory(createImageMemory(context.getDeviceInterface(), context.getDevice(),
1073 context.getDefaultAllocator(), *m_srcImage))
1074 , m_srcImageView(createImageAttachmentView(context.getDeviceInterface(), context.getDevice(), *m_srcImage,
1075 m_srcFormat, m_srcImageAspect))
1076 , m_srcPrimaryInputImageView(createSrcPrimaryInputImageView(context.getDeviceInterface(), context.getDevice(),
1077 *m_srcImage, m_srcFormat, m_srcImageAspect,
1078 m_separateStencilUsage))
1079 , m_srcSecondaryInputImageView(createSrcSecondaryInputImageView(context.getDeviceInterface(), context.getDevice(),
1080 *m_srcImage, m_srcFormat, m_srcImageAspect,
1081 m_separateStencilUsage))
1082 , m_srcInputImageReadLayout(chooseSrcInputImageLayout(config.groupParams))
1083
1084 , m_dstMultisampleImages(createMultisampleImages(context.getInstanceInterface(), context.getPhysicalDevice(),
1085 context.getDeviceInterface(), context.getDevice(), m_dstFormat,
1086 m_sampleCount, m_width, m_height))
1087 , m_dstMultisampleImageMemory(createImageMemory(context.getDeviceInterface(), context.getDevice(),
1088 context.getDefaultAllocator(), m_dstMultisampleImages))
1089 , m_dstMultisampleImageViews(createImageAttachmentViews(context.getDeviceInterface(), context.getDevice(),
1090 m_dstMultisampleImages, m_dstFormat,
1091 VK_IMAGE_ASPECT_COLOR_BIT))
1092
1093 , m_dstSinglesampleImages(createSingleSampleImages(context.getInstanceInterface(), context.getPhysicalDevice(),
1094 context.getDeviceInterface(), context.getDevice(), m_dstFormat,
1095 m_sampleCount, m_width, m_height))
1096 , m_dstSinglesampleImageMemory(createImageMemory(context.getDeviceInterface(), context.getDevice(),
1097 context.getDefaultAllocator(), m_dstSinglesampleImages))
1098 , m_dstSinglesampleImageViews(createImageAttachmentViews(context.getDeviceInterface(), context.getDevice(),
1099 m_dstSinglesampleImages, m_dstFormat,
1100 VK_IMAGE_ASPECT_COLOR_BIT))
1101
1102 , m_dstBuffers(createBuffers(context.getDeviceInterface(), context.getDevice(), m_dstFormat, m_sampleCount, m_width,
1103 m_height))
1104 , m_dstBufferMemory(createBufferMemory(context.getDeviceInterface(), context.getDevice(),
1105 context.getDefaultAllocator(), m_dstBuffers))
1106
1107 , m_renderPass(createRenderPass(context.getDeviceInterface(), context.getDevice(), m_srcFormat, m_dstFormat,
1108 m_sampleCount, m_groupParams->renderingType, m_separateStencilUsage))
1109 , m_framebuffer(createFramebuffer(context.getDeviceInterface(), context.getDevice(), *m_renderPass, *m_srcImageView,
1110 m_dstMultisampleImageViews, m_dstSinglesampleImageViews, m_width, m_height))
1111
1112 , m_renderPipelineLayout(m_groupParams->pipelineConstructionType, context.getDeviceInterface(), context.getDevice(),
1113 0, &m_pushConstantRange)
1114 , m_renderPipeline(context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(),
1115 context.getDevice(), context.getDeviceExtensions(), m_groupParams->pipelineConstructionType)
1116
1117 , m_splitDescriptorSetLayout(
1118 createSplitDescriptorSetLayout(context.getDeviceInterface(), context.getDevice(), m_srcFormat))
1119 , m_splitPipelineLayout(m_groupParams->pipelineConstructionType, context.getDeviceInterface(), context.getDevice(),
1120 *m_splitDescriptorSetLayout, &m_pushConstantRange)
1121 , m_splitDescriptorPool(createSplitDescriptorPool(context.getDeviceInterface(), context.getDevice()))
1122 , m_splitDescriptorSet(createSplitDescriptorSet(
1123 context.getDeviceInterface(), context.getDevice(), *m_splitDescriptorPool, *m_splitDescriptorSetLayout,
1124 *m_renderPass, *m_srcPrimaryInputImageView, *m_srcSecondaryInputImageView, m_srcInputImageReadLayout))
1125 , m_commandPool(createCommandPool(context.getDeviceInterface(), context.getDevice(),
1126 VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, context.getUniversalQueueFamilyIndex()))
1127 {
1128 createRenderPipeline();
1129 createSplitPipelines();
1130 }
1131
iterate(void)1132 tcu::TestStatus MultisampleRenderPassTestInstance::iterate(void)
1133 {
1134 switch (m_groupParams->renderingType)
1135 {
1136 case RENDERING_TYPE_RENDERPASS_LEGACY:
1137 return iterateInternal<RenderpassSubpass1>();
1138 case RENDERING_TYPE_RENDERPASS2:
1139 return iterateInternal<RenderpassSubpass2>();
1140 case RENDERING_TYPE_DYNAMIC_RENDERING:
1141 return iterateInternalDynamicRendering();
1142 default:
1143 TCU_THROW(InternalError, "Impossible");
1144 }
1145 }
1146
createRenderPipeline(void)1147 void MultisampleRenderPassTestInstance::createRenderPipeline(void)
1148 {
1149 const DeviceInterface &vkd(m_context.getDeviceInterface());
1150 VkDevice device(m_context.getDevice());
1151 const tcu::TextureFormat format(mapVkFormat(m_srcFormat));
1152 const bool isDepthFormat(tcu::hasDepthComponent(format.order));
1153 const bool isStencilFormat(tcu::hasStencilComponent(format.order));
1154 const bool isDepthStencilFormat(isDepthFormat || isStencilFormat);
1155 const BinaryCollection &binaryCollection(m_context.getBinaryCollection());
1156 ShaderWrapper vertexShaderModule(vkd, device, binaryCollection.get("quad-vert"), 0u);
1157 ShaderWrapper fragmentShaderModule(vkd, device, binaryCollection.get("quad-frag"), 0u);
1158 uint32_t colorAttachmentCount(!isDepthStencilFormat);
1159 const VkPipelineVertexInputStateCreateInfo vertexInputState = initVulkanStructure();
1160 const std::vector<VkViewport> viewports{makeViewport(m_width, m_height)};
1161 const std::vector<VkRect2D> scissors{makeRect2D(m_width, m_height)};
1162 PipelineRenderingCreateInfoWrapper renderingCreateInfoWrapper;
1163
1164 if (*m_renderPass == DE_NULL)
1165 {
1166 const uint32_t splitSubpassCount(deDivRoundUp32(m_sampleCount, MAX_COLOR_ATTACHMENT_COUNT));
1167 for (uint32_t splitSubpassIndex = 0; splitSubpassIndex < splitSubpassCount; splitSubpassIndex++)
1168 colorAttachmentCount += de::min((uint32_t)MAX_COLOR_ATTACHMENT_COUNT,
1169 m_sampleCount - splitSubpassIndex * MAX_COLOR_ATTACHMENT_COUNT);
1170 }
1171
1172 // Disable blending
1173 const std::vector<VkPipelineColorBlendAttachmentState> attachmentBlendStates(
1174 colorAttachmentCount,
1175 {VK_FALSE, VK_BLEND_FACTOR_SRC_ALPHA, VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, VK_BLEND_OP_ADD, VK_BLEND_FACTOR_ONE,
1176 VK_BLEND_FACTOR_ONE, VK_BLEND_OP_ADD,
1177 VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT});
1178 const VkPipelineMultisampleStateCreateInfo multisampleState{
1179 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
1180 DE_NULL,
1181 (VkPipelineMultisampleStateCreateFlags)0u,
1182
1183 sampleCountBitFromomSampleCount(m_sampleCount),
1184 VK_FALSE,
1185 0.0f,
1186 DE_NULL,
1187 VK_FALSE,
1188 VK_FALSE,
1189 };
1190 const VkPipelineDepthStencilStateCreateInfo depthStencilState{
1191 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
1192 DE_NULL,
1193 (VkPipelineDepthStencilStateCreateFlags)0u,
1194
1195 VK_TRUE,
1196 VK_TRUE,
1197 VK_COMPARE_OP_ALWAYS,
1198 VK_FALSE,
1199 VK_TRUE,
1200 {VK_STENCIL_OP_KEEP, VK_STENCIL_OP_INCREMENT_AND_WRAP, VK_STENCIL_OP_KEEP, VK_COMPARE_OP_ALWAYS, ~0u, ~0u,
1201 0xFFu / (m_sampleCount + 1)},
1202 {VK_STENCIL_OP_KEEP, VK_STENCIL_OP_INCREMENT_AND_WRAP, VK_STENCIL_OP_KEEP, VK_COMPARE_OP_ALWAYS, ~0u, ~0u,
1203 0xFFu / (m_sampleCount + 1)},
1204
1205 0.0f,
1206 1.0f};
1207
1208 const VkPipelineColorBlendStateCreateInfo blendState{
1209 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
1210 DE_NULL,
1211 (VkPipelineColorBlendStateCreateFlags)0u,
1212 VK_FALSE,
1213 VK_LOGIC_OP_COPY,
1214 colorAttachmentCount,
1215 ((isDepthStencilFormat && !!*m_renderPass) ? DE_NULL : attachmentBlendStates.data()),
1216 {0.0f, 0.0f, 0.0f, 0.0f}};
1217
1218 #ifndef CTS_USES_VULKANSC
1219 std::vector<VkFormat> colorAttachmentFormats(colorAttachmentCount, m_dstFormat);
1220 if (!isDepthStencilFormat)
1221 colorAttachmentFormats[0] = m_srcFormat;
1222
1223 VkPipelineRenderingCreateInfo renderingCreateInfo{VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
1224 DE_NULL,
1225 0u,
1226 (uint32_t)colorAttachmentFormats.size(),
1227 colorAttachmentFormats.data(),
1228 (isDepthFormat ? m_srcFormat : VK_FORMAT_UNDEFINED),
1229 (isStencilFormat ? m_srcFormat : VK_FORMAT_UNDEFINED)};
1230
1231 if (*m_renderPass == DE_NULL)
1232 renderingCreateInfoWrapper.ptr = &renderingCreateInfo;
1233 #endif // CTS_USES_VULKANSC
1234
1235 m_renderPipeline.setDefaultRasterizationState()
1236 .setupVertexInputState(&vertexInputState)
1237 .setupPreRasterizationShaderState(viewports, scissors, m_renderPipelineLayout, *m_renderPass, 0u,
1238 vertexShaderModule, 0u, ShaderWrapper(), ShaderWrapper(), ShaderWrapper(),
1239 nullptr, nullptr, renderingCreateInfoWrapper)
1240 .setupFragmentShaderState(m_renderPipelineLayout, *m_renderPass, 0u, fragmentShaderModule, &depthStencilState,
1241 &multisampleState)
1242 .setupFragmentOutputState(*m_renderPass, 0u, &blendState, &multisampleState)
1243 .setMonolithicPipelineLayout(m_renderPipelineLayout)
1244 .buildPipeline();
1245 }
1246
createSplitPipelines(void)1247 void MultisampleRenderPassTestInstance::createSplitPipelines(void)
1248 {
1249 const InstanceInterface &vki(m_context.getInstanceInterface());
1250 const DeviceInterface &vkd(m_context.getDeviceInterface());
1251 const VkPhysicalDevice physicalDevice(m_context.getPhysicalDevice());
1252 const VkDevice device(m_context.getDevice());
1253 const std::vector<string> &deviceExtensions(m_context.getDeviceExtensions());
1254
1255 const tcu::TextureFormat format(mapVkFormat(m_srcFormat));
1256 const bool isDepthFormat(tcu::hasDepthComponent(format.order));
1257 const bool isStencilFormat(tcu::hasStencilComponent(format.order));
1258 const bool isDepthStencilFormat(isDepthFormat || isStencilFormat);
1259 const uint32_t splitSubpassCount(deDivRoundUp32(m_sampleCount, MAX_COLOR_ATTACHMENT_COUNT));
1260 uint32_t colorAttachmentCount(de::min((uint32_t)MAX_COLOR_ATTACHMENT_COUNT, m_sampleCount));
1261 const BinaryCollection &binaryCollection(m_context.getBinaryCollection());
1262 ShaderWrapper vertexShaderModule(vkd, device, binaryCollection.get("quad-vert"), 0u);
1263 ShaderWrapper fragmentShaderModule(vkd, device, binaryCollection.get("quad-split-frag"), 0u);
1264
1265 DE_UNREF(isDepthStencilFormat);
1266
1267 PipelineRenderingCreateInfoWrapper renderingCreateInfoWrapper;
1268 RenderingAttachmentLocationInfoWrapper renderingAttachmentLocationInfoWrapper;
1269 RenderingInputAttachmentIndexInfoWrapper renderingInputAttachmentIndexInfoWrapper;
1270 const std::vector<VkViewport> viewports{makeViewport(m_width, m_height)};
1271 const std::vector<VkRect2D> scissors{makeRect2D(m_width, m_height)};
1272
1273 const VkPipelineVertexInputStateCreateInfo vertexInputState = initVulkanStructure();
1274 VkPipelineMultisampleStateCreateInfo multisampleState = initVulkanStructure();
1275 multisampleState.rasterizationSamples = sampleCountBitFromomSampleCount(m_sampleCount);
1276
1277 // Disable blending
1278 const VkPipelineColorBlendAttachmentState attachmentBlendState{
1279 VK_FALSE,
1280 VK_BLEND_FACTOR_SRC_ALPHA,
1281 VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
1282 VK_BLEND_OP_ADD,
1283 VK_BLEND_FACTOR_ONE,
1284 VK_BLEND_FACTOR_ONE,
1285 VK_BLEND_OP_ADD,
1286 VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT};
1287
1288 const uint32_t maximalNumberOfAttachments = 1 + splitSubpassCount * MAX_COLOR_ATTACHMENT_COUNT;
1289 const std::vector<VkPipelineColorBlendAttachmentState> attachmentBlendStates(maximalNumberOfAttachments,
1290 attachmentBlendState);
1291
1292 VkPipelineColorBlendStateCreateInfo blendState{VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
1293 DE_NULL,
1294 (VkPipelineColorBlendStateCreateFlags)0u,
1295 VK_FALSE,
1296 VK_LOGIC_OP_COPY,
1297 colorAttachmentCount,
1298 attachmentBlendStates.data(),
1299 {0.0f, 0.0f, 0.0f, 0.0f}};
1300
1301 #ifndef CTS_USES_VULKANSC
1302 uint32_t depthAttachmentInputIndex(0);
1303 uint32_t stencilAttachmentInputIndex(0);
1304 std::vector<VkFormat> colorAttachmentFormats(maximalNumberOfAttachments, m_dstFormat);
1305 std::vector<uint32_t> colorAttachmentLocations;
1306 std::vector<uint32_t> colorAttachmentInputIndices;
1307 VkRenderingAttachmentLocationInfoKHR renderingAttachmentLocation;
1308 VkRenderingInputAttachmentIndexInfoKHR renderingInputAttachmentIndexInfo;
1309
1310 if (!isDepthStencilFormat)
1311 colorAttachmentFormats[0] = m_srcFormat;
1312
1313 VkPipelineRenderingCreateInfo renderingCreateInfo{VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO,
1314 &renderingInputAttachmentIndexInfo,
1315 0u,
1316 0u,
1317 colorAttachmentFormats.data(),
1318 (isDepthFormat ? m_srcFormat : VK_FORMAT_UNDEFINED),
1319 (isStencilFormat ? m_srcFormat : VK_FORMAT_UNDEFINED)};
1320 #endif // CTS_USES_VULKANSC
1321
1322 m_splitPipelines.reserve(splitSubpassCount);
1323 for (uint32_t ndx = 0; ndx < splitSubpassCount; ndx++)
1324 {
1325 #ifndef CTS_USES_VULKANSC
1326 if (*m_renderPass == DE_NULL)
1327 {
1328 colorAttachmentCount =
1329 !isDepthStencilFormat + splitSubpassCount * de::min((uint32_t)MAX_COLOR_ATTACHMENT_COUNT,
1330 m_sampleCount - ndx * MAX_COLOR_ATTACHMENT_COUNT);
1331 blendState.attachmentCount = colorAttachmentCount;
1332 renderingCreateInfo.colorAttachmentCount = colorAttachmentCount;
1333
1334 colorAttachmentLocations.resize(colorAttachmentCount);
1335 colorAttachmentInputIndices.resize(colorAttachmentCount);
1336
1337 renderingAttachmentLocation =
1338 getRenderingAttachmentLocationInfo(colorAttachmentLocations, isDepthStencilFormat, m_sampleCount, ndx);
1339 renderingInputAttachmentIndexInfo =
1340 getRenderingInputAttachmentIndexInfo(colorAttachmentInputIndices, depthAttachmentInputIndex,
1341 stencilAttachmentInputIndex, isDepthFormat, isStencilFormat);
1342 renderingCreateInfoWrapper.ptr = &renderingCreateInfo;
1343 renderingAttachmentLocationInfoWrapper.ptr = &renderingAttachmentLocation;
1344 renderingInputAttachmentIndexInfoWrapper.ptr = &renderingInputAttachmentIndexInfo;
1345 }
1346 #endif // CTS_USES_VULKANSC
1347
1348 m_splitPipelines.emplace_back(vki, vkd, physicalDevice, device, deviceExtensions,
1349 m_groupParams->pipelineConstructionType);
1350 m_splitPipelines[ndx]
1351 .setDefaultDepthStencilState()
1352 .setDefaultRasterizationState()
1353 .setupVertexInputState(&vertexInputState)
1354 .setupPreRasterizationShaderState(viewports, scissors, m_splitPipelineLayout, *m_renderPass, ndx + 1u,
1355 vertexShaderModule, 0u, ShaderWrapper(), ShaderWrapper(), ShaderWrapper(),
1356 nullptr, nullptr, renderingCreateInfoWrapper)
1357 .setupFragmentShaderState(m_splitPipelineLayout, *m_renderPass, ndx + 1u, fragmentShaderModule, 0u,
1358 &multisampleState, 0, 0, {}, renderingInputAttachmentIndexInfoWrapper)
1359 .setupFragmentOutputState(*m_renderPass, ndx + 1u, &blendState, &multisampleState, 0, {},
1360 renderingAttachmentLocationInfoWrapper)
1361 .setMonolithicPipelineLayout(m_splitPipelineLayout)
1362 .buildPipeline();
1363 }
1364 }
1365
1366 template <typename RenderpassSubpass>
iterateInternal(void)1367 tcu::TestStatus MultisampleRenderPassTestInstance::iterateInternal(void)
1368 {
1369 const DeviceInterface &vkd(m_context.getDeviceInterface());
1370 const VkDevice device(m_context.getDevice());
1371 const Unique<VkCommandBuffer> commandBuffer(
1372 allocateCommandBuffer(vkd, device, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1373 const typename RenderpassSubpass::SubpassBeginInfo subpassBeginInfo(DE_NULL, VK_SUBPASS_CONTENTS_INLINE);
1374 const typename RenderpassSubpass::SubpassEndInfo subpassEndInfo(DE_NULL);
1375
1376 beginCommandBuffer(vkd, *commandBuffer);
1377
1378 const VkRenderPassBeginInfo beginInfo = {VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
1379 DE_NULL,
1380
1381 *m_renderPass,
1382 *m_framebuffer,
1383
1384 {{0u, 0u}, {m_width, m_height}},
1385
1386 0u,
1387 DE_NULL};
1388
1389 RenderpassSubpass::cmdBeginRenderPass(vkd, *commandBuffer, &beginInfo, &subpassBeginInfo);
1390
1391 // Stencil needs to be cleared if it exists.
1392 if (tcu::hasStencilComponent(mapVkFormat(m_srcFormat).order))
1393 {
1394 const VkClearAttachment clearAttachment{
1395 VK_IMAGE_ASPECT_STENCIL_BIT, // VkImageAspectFlags aspectMask;
1396 0, // uint32_t colorAttachment;
1397 makeClearValueDepthStencil(0, 0) // VkClearValue clearValue;
1398 };
1399
1400 const VkClearRect clearRect{
1401 {{0u, 0u}, {m_width, m_height}},
1402 0, // uint32_t baseArrayLayer;
1403 1 // uint32_t layerCount;
1404 };
1405
1406 vkd.cmdClearAttachments(*commandBuffer, 1, &clearAttachment, 1, &clearRect);
1407 }
1408
1409 drawFirstSubpass(vkd, *commandBuffer);
1410
1411 for (uint32_t splitPipelineNdx = 0; splitPipelineNdx < m_splitPipelines.size(); splitPipelineNdx++)
1412 {
1413 RenderpassSubpass::cmdNextSubpass(vkd, *commandBuffer, &subpassBeginInfo, &subpassEndInfo);
1414 drawNextSubpass(vkd, *commandBuffer, splitPipelineNdx);
1415 }
1416
1417 RenderpassSubpass::cmdEndRenderPass(vkd, *commandBuffer, &subpassEndInfo);
1418
1419 postRenderCommands(vkd, *commandBuffer);
1420
1421 endCommandBuffer(vkd, *commandBuffer);
1422
1423 submitCommandsAndWait(vkd, device, m_context.getUniversalQueue(), *commandBuffer);
1424
1425 return verifyResult();
1426 }
1427
iterateInternalDynamicRendering()1428 tcu::TestStatus MultisampleRenderPassTestInstance::iterateInternalDynamicRendering()
1429 {
1430 #ifndef CTS_USES_VULKANSC
1431
1432 const DeviceInterface &vk(m_context.getDeviceInterface());
1433 const VkDevice device(m_context.getDevice());
1434 const Unique<VkCommandBuffer> cmdBuffer(
1435 allocateCommandBuffer(vk, device, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1436 Move<VkCommandBuffer> secCmdBuffer;
1437
1438 const uint32_t splitSubpassCount(deDivRoundUp32(m_sampleCount, MAX_COLOR_ATTACHMENT_COUNT));
1439 const VkClearValue clearValue(makeClearValueColor(tcu::Vec4(0.0f)));
1440 const tcu::TextureFormat format(mapVkFormat(m_srcFormat));
1441 const bool isDepthFormat(tcu::hasDepthComponent(format.order));
1442 const bool isStencilFormat(tcu::hasStencilComponent(format.order));
1443 const bool isDepthStencilFormat(isDepthFormat || isStencilFormat);
1444 VkResolveModeFlagBits resolveMode(VK_RESOLVE_MODE_AVERAGE_BIT);
1445 VkImageAspectFlags aspectMask(VK_IMAGE_ASPECT_NONE);
1446
1447 if (isDepthFormat)
1448 aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
1449 if (isStencilFormat)
1450 aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
1451 if (aspectMask == VK_IMAGE_ASPECT_NONE)
1452 {
1453 aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
1454 if (isIntFormat(m_srcFormat) || isUintFormat(m_srcFormat))
1455 resolveMode = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT;
1456 }
1457
1458 uint32_t colorAttachmentIndex = !isDepthStencilFormat;
1459 uint32_t colorAttachmentCount = colorAttachmentIndex;
1460 for (uint32_t splitSubpassIndex = 0; splitSubpassIndex < splitSubpassCount; splitSubpassIndex++)
1461 colorAttachmentCount += de::min((uint32_t)MAX_COLOR_ATTACHMENT_COUNT,
1462 m_sampleCount - splitSubpassIndex * MAX_COLOR_ATTACHMENT_COUNT);
1463
1464 uint32_t depthAttachmentInputIndex(0);
1465 uint32_t stencilAttachmentInputIndex(0);
1466 std::vector<uint32_t> colorAttachmentInputIndices(colorAttachmentCount, VK_ATTACHMENT_UNUSED);
1467 std::vector<uint32_t> colorAttachmentLocations(colorAttachmentCount, VK_ATTACHMENT_UNUSED);
1468
1469 VkRenderingAttachmentInfo depthAttachment{
1470 VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
1471 DE_NULL,
1472 *m_srcImageView, // VkImageView imageView;
1473 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout imageLayout;
1474 VK_RESOLVE_MODE_NONE, // VkResolveModeFlagBits resolveMode;
1475 DE_NULL, // VkImageView resolveImageView;
1476 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout resolveImageLayout;
1477 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp loadOp;
1478 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
1479 clearValue // VkClearValue clearValue;
1480 };
1481 std::vector<VkRenderingAttachmentInfo> colorAttachments(colorAttachmentCount, depthAttachment);
1482
1483 // If depth/stencil attachments are used then they will be used as input attachments
1484 depthAttachment.imageLayout = m_srcInputImageReadLayout;
1485
1486 // If stencil attachment is used then we need to clear it
1487 VkRenderingAttachmentInfo stencilAttachment = depthAttachment;
1488 stencilAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
1489
1490 // If source image has color aspect then we will use first color attachment as input for second subpass
1491 if (colorAttachmentIndex)
1492 colorAttachments[0].imageLayout = m_srcInputImageReadLayout;
1493
1494 for (uint32_t i = 0; i < m_dstMultisampleImageViews.size(); ++i)
1495 {
1496 colorAttachments[colorAttachmentIndex].imageView = **m_dstMultisampleImageViews[i];
1497 colorAttachments[colorAttachmentIndex].resolveImageView = **m_dstSinglesampleImageViews[i];
1498 colorAttachments[colorAttachmentIndex].resolveMode = resolveMode;
1499 ++colorAttachmentIndex;
1500 }
1501 DE_ASSERT(colorAttachmentIndex == colorAttachmentCount);
1502
1503 VkRenderingInfo renderingInfo{
1504 VK_STRUCTURE_TYPE_RENDERING_INFO,
1505 DE_NULL,
1506 0, // VkRenderingFlagsKHR flags;
1507 makeRect2D(m_width, m_height), // VkRect2D renderArea;
1508 1u, // uint32_t layerCount;
1509 0u, // uint32_t viewMask;
1510 (uint32_t)colorAttachments.size(), // uint32_t colorAttachmentCount;
1511 colorAttachments.data(), // const VkRenderingAttachmentInfoKHR* pColorAttachments;
1512 isDepthFormat ? &depthAttachment : DE_NULL, // const VkRenderingAttachmentInfoKHR* pDepthAttachment;
1513 isStencilFormat ? &stencilAttachment : DE_NULL, // const VkRenderingAttachmentInfoKHR* pStencilAttachment;
1514 };
1515
1516 auto renderingInputAttachmentIndexInfo =
1517 getRenderingInputAttachmentIndexInfo(colorAttachmentInputIndices, depthAttachmentInputIndex,
1518 stencilAttachmentInputIndex, isDepthFormat, isStencilFormat);
1519 VkRenderingAttachmentLocationInfoKHR renderingAttachmentLocation;
1520
1521 if (m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
1522 {
1523 secCmdBuffer = allocateCommandBuffer(vk, device, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
1524
1525 // record secondary command buffer
1526 beginSecondaryCmdBuffer(vk, *secCmdBuffer, m_srcFormat, m_dstFormat, colorAttachmentCount, m_sampleCount);
1527 vk.cmdBeginRendering(*secCmdBuffer, &renderingInfo);
1528
1529 drawFirstSubpass(vk, *secCmdBuffer);
1530 inbetweenRenderCommands(vk, *secCmdBuffer, aspectMask);
1531
1532 for (uint32_t splitPipelineNdx = 0; splitPipelineNdx < m_splitPipelines.size(); splitPipelineNdx++)
1533 {
1534 renderingAttachmentLocation = getRenderingAttachmentLocationInfo(
1535 colorAttachmentLocations, isDepthStencilFormat, m_sampleCount, splitPipelineNdx);
1536 vk.cmdSetRenderingAttachmentLocationsKHR(*secCmdBuffer, &renderingAttachmentLocation);
1537 vk.cmdSetRenderingInputAttachmentIndicesKHR(*secCmdBuffer, &renderingInputAttachmentIndexInfo);
1538
1539 drawNextSubpass(vk, *secCmdBuffer, splitPipelineNdx);
1540 }
1541
1542 vk.cmdEndRendering(*secCmdBuffer);
1543 endCommandBuffer(vk, *secCmdBuffer);
1544
1545 // record primary command buffer
1546 beginCommandBuffer(vk, *cmdBuffer);
1547 preRenderCommands(vk, *cmdBuffer, aspectMask);
1548 vk.cmdExecuteCommands(*cmdBuffer, 1u, &*secCmdBuffer);
1549 postRenderCommands(vk, *cmdBuffer);
1550 endCommandBuffer(vk, *cmdBuffer);
1551 }
1552 else
1553 {
1554 beginCommandBuffer(vk, *cmdBuffer);
1555
1556 preRenderCommands(vk, *cmdBuffer, aspectMask);
1557
1558 vk.cmdBeginRendering(*cmdBuffer, &renderingInfo);
1559
1560 drawFirstSubpass(vk, *cmdBuffer);
1561
1562 inbetweenRenderCommands(vk, *cmdBuffer, aspectMask);
1563
1564 for (uint32_t splitPipelineNdx = 0; splitPipelineNdx < m_splitPipelines.size(); splitPipelineNdx++)
1565 {
1566 renderingAttachmentLocation = getRenderingAttachmentLocationInfo(
1567 colorAttachmentLocations, isDepthStencilFormat, m_sampleCount, splitPipelineNdx);
1568 vk.cmdSetRenderingAttachmentLocationsKHR(*cmdBuffer, &renderingAttachmentLocation);
1569 vk.cmdSetRenderingInputAttachmentIndicesKHR(*cmdBuffer, &renderingInputAttachmentIndexInfo);
1570
1571 drawNextSubpass(vk, *cmdBuffer, splitPipelineNdx);
1572 }
1573
1574 vk.cmdEndRendering(*cmdBuffer);
1575
1576 postRenderCommands(vk, *cmdBuffer);
1577
1578 endCommandBuffer(vk, *cmdBuffer);
1579 }
1580
1581 submitCommandsAndWait(vk, device, m_context.getUniversalQueue(), *cmdBuffer);
1582
1583 #endif // CTS_USES_VULKANSC
1584
1585 return verifyResult();
1586 }
1587
1588 #ifndef CTS_USES_VULKANSC
preRenderCommands(const DeviceInterface & vk,VkCommandBuffer cmdBuffer,VkImageAspectFlags aspectMask)1589 void MultisampleRenderPassTestInstance::preRenderCommands(const DeviceInterface &vk, VkCommandBuffer cmdBuffer,
1590 VkImageAspectFlags aspectMask)
1591 {
1592 const tcu::TextureFormat format(mapVkFormat(m_srcFormat));
1593 const VkImageSubresourceRange srcSubresourceRange(makeImageSubresourceRange(aspectMask, 0, 1, 0, 1));
1594 const VkImageSubresourceRange dstSubresourceRange(makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1));
1595
1596 // Memory barrier to set singlesamepled image layout to COLOR_ATTACHMENT_OPTIMAL
1597 VkPipelineStageFlags dstStageMaskForSourceImage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
1598 VkImageMemoryBarrier srcImageBarrier(makeImageMemoryBarrier(0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
1599 VK_IMAGE_LAYOUT_UNDEFINED, m_srcInputImageReadLayout,
1600 *m_srcImage, srcSubresourceRange));
1601
1602 if (tcu::hasDepthComponent(format.order) || tcu::hasStencilComponent(format.order))
1603 {
1604 dstStageMaskForSourceImage = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
1605 srcImageBarrier.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
1606 }
1607
1608 // Memory barriers to set singlesamepled and multisample images layout to COLOR_ATTACHMENT_OPTIMAL
1609 std::vector<VkImageMemoryBarrier> dstImageBarriers(
1610 m_dstSinglesampleImages.size() + m_dstMultisampleImages.size(),
1611 makeImageMemoryBarrier(0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
1612 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, DE_NULL, dstSubresourceRange));
1613 for (size_t dstNdx = 0; dstNdx < m_dstSinglesampleImages.size(); dstNdx++)
1614 dstImageBarriers[dstNdx].image = **m_dstSinglesampleImages[dstNdx];
1615 for (size_t dstNdx = m_dstSinglesampleImages.size(); dstNdx < dstImageBarriers.size(); dstNdx++)
1616 dstImageBarriers[dstNdx].image = **m_dstMultisampleImages[dstNdx - m_dstSinglesampleImages.size()];
1617
1618 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, dstStageMaskForSourceImage, 0u, 0u, DE_NULL, 0u,
1619 DE_NULL, 1u, &srcImageBarrier);
1620 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
1621 0u, 0u, DE_NULL, 0u, DE_NULL, (uint32_t)dstImageBarriers.size(), dstImageBarriers.data());
1622 }
1623
inbetweenRenderCommands(const DeviceInterface & vk,VkCommandBuffer cmdBuffer,VkImageAspectFlags aspectMask)1624 void MultisampleRenderPassTestInstance::inbetweenRenderCommands(const DeviceInterface &vk, VkCommandBuffer cmdBuffer,
1625 VkImageAspectFlags aspectMask)
1626 {
1627 const VkImageSubresourceRange srcSubresourceRange(makeImageSubresourceRange(aspectMask, 0, 1, 0, 1));
1628 VkAccessFlags dstAccessMask(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
1629 VkPipelineStageFlags dstStageMaskForSourceImage(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
1630
1631 if (aspectMask != VK_IMAGE_ASPECT_COLOR_BIT)
1632 {
1633 dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
1634 dstStageMaskForSourceImage = VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
1635 }
1636
1637 VkImageMemoryBarrier imageBarrier(makeImageMemoryBarrier(dstAccessMask, VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
1638 m_srcInputImageReadLayout, m_srcInputImageReadLayout,
1639 *m_srcImage, srcSubresourceRange));
1640 vk.cmdPipelineBarrier(cmdBuffer, dstStageMaskForSourceImage, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
1641 VK_DEPENDENCY_BY_REGION_BIT, 0u, DE_NULL, 0u, DE_NULL, 1u, &imageBarrier);
1642 }
1643 #endif // CTS_USES_VULKANSC
1644
drawFirstSubpass(const DeviceInterface & vk,VkCommandBuffer cmdBuffer)1645 void MultisampleRenderPassTestInstance::drawFirstSubpass(const DeviceInterface &vk, VkCommandBuffer cmdBuffer)
1646 {
1647 vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_renderPipeline.getPipeline());
1648 for (uint32_t sampleNdx = 0; sampleNdx < m_sampleCount; sampleNdx++)
1649 {
1650 vk.cmdPushConstants(cmdBuffer, *m_renderPipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0u, sizeof(sampleNdx),
1651 &sampleNdx);
1652 vk.cmdDraw(cmdBuffer, 6u, 1u, 0u, 0u);
1653 }
1654 }
1655
drawNextSubpass(const DeviceInterface & vk,VkCommandBuffer cmdBuffer,uint32_t splitPipelineNdx)1656 void MultisampleRenderPassTestInstance::drawNextSubpass(const DeviceInterface &vk, VkCommandBuffer cmdBuffer,
1657 uint32_t splitPipelineNdx)
1658 {
1659 vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_splitPipelines[splitPipelineNdx].getPipeline());
1660 vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_splitPipelineLayout, 0u, 1u,
1661 &*m_splitDescriptorSet, 0u, DE_NULL);
1662 vk.cmdPushConstants(cmdBuffer, *m_splitPipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0u, sizeof(splitPipelineNdx),
1663 &splitPipelineNdx);
1664 vk.cmdDraw(cmdBuffer, 6u, 1u, 0u, 0u);
1665 }
1666
postRenderCommands(const DeviceInterface & vk,VkCommandBuffer cmdBuffer)1667 void MultisampleRenderPassTestInstance::postRenderCommands(const DeviceInterface &vk, VkCommandBuffer cmdBuffer)
1668 {
1669 VkImageLayout oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
1670 if (m_groupParams->renderingType != RENDERING_TYPE_DYNAMIC_RENDERING)
1671 oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
1672
1673 for (size_t dstNdx = 0; dstNdx < m_dstSinglesampleImages.size(); dstNdx++)
1674 copyImageToBuffer(vk, cmdBuffer, **m_dstSinglesampleImages[dstNdx], **m_dstBuffers[dstNdx],
1675 tcu::IVec2(m_width, m_height), VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, oldLayout);
1676 }
1677
verifyResult(void)1678 tcu::TestStatus MultisampleRenderPassTestInstance::verifyResult(void)
1679 {
1680 const DeviceInterface &vkd(m_context.getDeviceInterface());
1681 const VkDevice device(m_context.getDevice());
1682 const tcu::TextureFormat format(mapVkFormat(m_dstFormat));
1683 const tcu::TextureFormat srcFormat(mapVkFormat(m_srcFormat));
1684 const bool verifyDepth(m_separateStencilUsage ? (m_separateStencilUsage == TEST_DEPTH) :
1685 tcu::hasDepthComponent(srcFormat.order));
1686 const bool verifyStencil(m_separateStencilUsage ? (m_separateStencilUsage == TEST_STENCIL) :
1687 tcu::hasStencilComponent(srcFormat.order));
1688
1689 for (uint32_t sampleNdx = 0; sampleNdx < m_sampleCount; sampleNdx++)
1690 {
1691 Allocation *dstBufMem = m_dstBufferMemory[sampleNdx].get();
1692 invalidateAlloc(vkd, device, *dstBufMem);
1693
1694 const std::string name("Sample" + de::toString(sampleNdx));
1695 const void *const ptr(dstBufMem->getHostPtr());
1696 const tcu::ConstPixelBufferAccess access(format, m_width, m_height, 1, ptr);
1697 tcu::TextureLevel reference(format, m_width, m_height);
1698
1699 if (verifyDepth || verifyStencil)
1700 {
1701 if (verifyDepth)
1702 {
1703 for (uint32_t y = 0; y < m_height; y++)
1704 for (uint32_t x = 0; x < m_width; x++)
1705 {
1706 const uint32_t x1 = x ^ sampleNdx;
1707 const uint32_t y1 = y ^ sampleNdx;
1708 const float range = 1.0f;
1709 float depth = 0.0f;
1710 uint32_t divider = 2;
1711
1712 // \note Limited to ten bits since the target is 32x32, so there are 10 input bits
1713 for (size_t bitNdx = 0; bitNdx < 10; bitNdx++)
1714 {
1715 depth += (range / (float)divider) *
1716 (((bitNdx % 2 == 0 ? x1 : y1) & (0x1u << (bitNdx / 2u))) == 0u ? 0u : 1u);
1717 divider *= 2;
1718 }
1719
1720 reference.getAccess().setPixel(Vec4(depth, 0.0f, 0.0f, 0.0f), x, y);
1721 }
1722 }
1723 if (verifyStencil)
1724 {
1725 for (uint32_t y = 0; y < m_height; y++)
1726 for (uint32_t x = 0; x < m_width; x++)
1727 {
1728 const uint32_t stencil = sampleNdx + 1u;
1729
1730 if (verifyDepth)
1731 {
1732 const Vec4 src(reference.getAccess().getPixel(x, y));
1733
1734 reference.getAccess().setPixel(Vec4(src.x(), (float)stencil, 0.0f, 0.0f), x, y);
1735 }
1736 else
1737 reference.getAccess().setPixel(Vec4((float)stencil, 0.0f, 0.0f, 0.0f), x, y);
1738 }
1739 }
1740 {
1741 const Vec4 threshold(verifyDepth ? (1.0f / 1024.0f) : 0.0f, 0.0f, 0.0f, 0.0f);
1742
1743 if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), name.c_str(), "",
1744 reference.getAccess(), access, threshold, tcu::COMPARE_LOG_ON_ERROR))
1745 m_resultCollector.fail("Compare failed for sample " + de::toString(sampleNdx));
1746 }
1747 }
1748 else
1749 {
1750 const tcu::TextureChannelClass channelClass(tcu::getTextureChannelClass(format.type));
1751
1752 switch (channelClass)
1753 {
1754 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
1755 {
1756 const UVec4 bits(tcu::getTextureFormatBitDepth(format).cast<uint32_t>());
1757 const UVec4 minValue(0);
1758 const UVec4 range(UVec4(1u) << tcu::min(bits, UVec4(31)));
1759 const int componentCount(tcu::getNumUsedChannels(format.order));
1760 const uint32_t bitSize(bits[0] + bits[1] + bits[2] + bits[3]);
1761
1762 for (uint32_t y = 0; y < m_height; y++)
1763 for (uint32_t x = 0; x < m_width; x++)
1764 {
1765 const uint32_t x1 = x ^ sampleNdx;
1766 const uint32_t y1 = y ^ sampleNdx;
1767 UVec4 color(minValue);
1768 uint32_t dstBitsUsed[4] = {0u, 0u, 0u, 0u};
1769 uint32_t nextSrcBit = 0;
1770 uint32_t divider = 2;
1771
1772 // \note Limited to ten bits since the target is 32x32, so there are 10 input bits
1773 while (nextSrcBit < de::min(bitSize, 10u))
1774 {
1775 for (int compNdx = 0; compNdx < componentCount; compNdx++)
1776 {
1777 if (dstBitsUsed[compNdx] > bits[compNdx])
1778 continue;
1779
1780 color[compNdx] +=
1781 (range[compNdx] / divider) *
1782 (((nextSrcBit % 2 == 0 ? x1 : y1) & (0x1u << (nextSrcBit / 2u))) == 0u ? 0u : 1u);
1783
1784 nextSrcBit++;
1785 dstBitsUsed[compNdx]++;
1786 }
1787
1788 divider *= 2;
1789 }
1790
1791 reference.getAccess().setPixel(color, x, y);
1792 }
1793
1794 if (!tcu::intThresholdCompare(m_context.getTestContext().getLog(), name.c_str(), "",
1795 reference.getAccess(), access, UVec4(0u), tcu::COMPARE_LOG_ON_ERROR))
1796 m_resultCollector.fail("Compare failed for sample " + de::toString(sampleNdx));
1797
1798 break;
1799 }
1800
1801 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
1802 {
1803 const UVec4 bits(tcu::getTextureFormatBitDepth(format).cast<uint32_t>());
1804 const IVec4 minValue(0);
1805 const IVec4 range((UVec4(1u) << tcu::min(bits, UVec4(30))).cast<int32_t>());
1806 const int componentCount(tcu::getNumUsedChannels(format.order));
1807 const uint32_t bitSize(bits[0] + bits[1] + bits[2] + bits[3]);
1808
1809 for (uint32_t y = 0; y < m_height; y++)
1810 for (uint32_t x = 0; x < m_width; x++)
1811 {
1812 const uint32_t x1 = x ^ sampleNdx;
1813 const uint32_t y1 = y ^ sampleNdx;
1814 IVec4 color(minValue);
1815 uint32_t dstBitsUsed[4] = {0u, 0u, 0u, 0u};
1816 uint32_t nextSrcBit = 0;
1817 uint32_t divider = 2;
1818
1819 // \note Limited to ten bits since the target is 32x32, so there are 10 input bits
1820 while (nextSrcBit < de::min(bitSize, 10u))
1821 {
1822 for (int compNdx = 0; compNdx < componentCount; compNdx++)
1823 {
1824 if (dstBitsUsed[compNdx] > bits[compNdx])
1825 continue;
1826
1827 color[compNdx] +=
1828 (range[compNdx] / divider) *
1829 (((nextSrcBit % 2 == 0 ? x1 : y1) & (0x1u << (nextSrcBit / 2u))) == 0u ? 0u : 1u);
1830
1831 nextSrcBit++;
1832 dstBitsUsed[compNdx]++;
1833 }
1834
1835 divider *= 2;
1836 }
1837
1838 reference.getAccess().setPixel(color, x, y);
1839 }
1840
1841 if (!tcu::intThresholdCompare(m_context.getTestContext().getLog(), name.c_str(), "",
1842 reference.getAccess(), access, UVec4(0u), tcu::COMPARE_LOG_ON_ERROR))
1843 m_resultCollector.fail("Compare failed for sample " + de::toString(sampleNdx));
1844
1845 break;
1846 }
1847
1848 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
1849 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
1850 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
1851 {
1852 const tcu::TextureFormatInfo info(tcu::getTextureFormatInfo(format));
1853 const UVec4 bits(tcu::getTextureFormatBitDepth(format).cast<uint32_t>());
1854 const Vec4 minLimit(-65536.0);
1855 const Vec4 maxLimit(65536.0);
1856 const Vec4 minValue(tcu::max(info.valueMin, minLimit));
1857 const Vec4 range(tcu::min(info.valueMax, maxLimit) - minValue);
1858 const bool isAlphaOnly = isAlphaOnlyFormat(m_dstFormat);
1859 const int componentCount(isAlphaOnly ? 4 : tcu::getNumUsedChannels(format.order));
1860 const uint32_t bitSize(bits[0] + bits[1] + bits[2] + bits[3]);
1861
1862 for (uint32_t y = 0; y < m_height; y++)
1863 for (uint32_t x = 0; x < m_width; x++)
1864 {
1865 const uint32_t x1 = x ^ sampleNdx;
1866 const uint32_t y1 = y ^ sampleNdx;
1867 Vec4 color(minValue);
1868 uint32_t dstBitsUsed[4] = {0u, 0u, 0u, 0u};
1869 uint32_t nextSrcBit = 0;
1870 uint32_t divider = 2;
1871
1872 // \note Limited to ten bits since the target is 32x32, so there are 10 input bits
1873 while (nextSrcBit < de::min(bitSize, 10u))
1874 {
1875 for (int compNdx = 0; compNdx < componentCount; compNdx++)
1876 {
1877 if (dstBitsUsed[compNdx] > bits[compNdx])
1878 continue;
1879
1880 color[compNdx] +=
1881 (range[compNdx] / (float)divider) *
1882 (((nextSrcBit % 2 == 0 ? x1 : y1) & (0x1u << (nextSrcBit / 2u))) == 0u ? 0u : 1u);
1883
1884 nextSrcBit++;
1885 dstBitsUsed[compNdx]++;
1886 }
1887
1888 divider *= 2;
1889 }
1890
1891 if (tcu::isSRGB(format))
1892 reference.getAccess().setPixel(tcu::linearToSRGB(color), x, y);
1893 else
1894 reference.getAccess().setPixel(color, x, y);
1895 }
1896
1897 if (channelClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT)
1898 {
1899 // Convert target format ulps to float ulps and allow 64ulp differences
1900 const UVec4 threshold(
1901 64u *
1902 (UVec4(1u) << (UVec4(23) - tcu::getTextureFormatMantissaBitDepth(format).cast<uint32_t>())));
1903
1904 if (!tcu::floatUlpThresholdCompare(m_context.getTestContext().getLog(), name.c_str(), "",
1905 reference.getAccess(), access, threshold,
1906 tcu::COMPARE_LOG_ON_ERROR))
1907 m_resultCollector.fail("Compare failed for sample " + de::toString(sampleNdx));
1908 }
1909 else
1910 {
1911 // Allow error of 4 times the minimum presentable difference
1912 const Vec4 threshold(
1913 4.0f * 1.0f /
1914 ((UVec4(1u) << tcu::getTextureFormatMantissaBitDepth(format).cast<uint32_t>()) - 1u)
1915 .cast<float>());
1916
1917 if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), name.c_str(), "",
1918 reference.getAccess(), access, threshold,
1919 tcu::COMPARE_LOG_ON_ERROR))
1920 m_resultCollector.fail("Compare failed for sample " + de::toString(sampleNdx));
1921 }
1922
1923 break;
1924 }
1925
1926 default:
1927 DE_FATAL("Unknown channel class");
1928 }
1929 }
1930 }
1931
1932 return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage());
1933 }
1934
1935 struct Programs
1936 {
initvkt::renderpass::__anon7a6d0e070111::Programs1937 void init(vk::SourceCollections &dst, TestConfig config) const
1938 {
1939 const tcu::TextureFormat format(mapVkFormat(config.format));
1940 const tcu::TextureChannelClass channelClass(tcu::getTextureChannelClass(format.type));
1941 const bool testDepth(config.separateStencilUsage ? (config.separateStencilUsage == TEST_DEPTH) :
1942 tcu::hasDepthComponent(format.order));
1943 const bool testStencil(config.separateStencilUsage ? (config.separateStencilUsage == TEST_STENCIL) :
1944 tcu::hasStencilComponent(format.order));
1945
1946 dst.glslSources.add("quad-vert") << glu::VertexSource(
1947 "#version 450\n"
1948 "out gl_PerVertex {\n"
1949 "\tvec4 gl_Position;\n"
1950 "};\n"
1951 "highp float;\n"
1952 "void main (void) {\n"
1953 "\tgl_Position = vec4(((gl_VertexIndex + 2) / 3) % 2 == 0 ? -1.0 : 1.0,\n"
1954 "\t ((gl_VertexIndex + 1) / 3) % 2 == 0 ? -1.0 : 1.0, 0.0, 1.0);\n"
1955 "}\n");
1956
1957 if (testDepth)
1958 {
1959 const Vec4 minValue(0.0f);
1960 const Vec4 range(1.0f);
1961 std::ostringstream fragmentShader;
1962
1963 fragmentShader << "#version 450\n"
1964 "layout(push_constant) uniform PushConstant {\n"
1965 "\thighp uint sampleIndex;\n"
1966 "} pushConstants;\n"
1967 "void main (void)\n"
1968 "{\n"
1969 "\thighp uint sampleIndex = pushConstants.sampleIndex;\n"
1970 "\tgl_SampleMask[0] = int((~0x0u) << sampleIndex);\n"
1971 "\thighp float depth;\n"
1972 "\thighp uint x = sampleIndex ^ uint(gl_FragCoord.x);\n"
1973 "\thighp uint y = sampleIndex ^ uint(gl_FragCoord.y);\n";
1974
1975 fragmentShader << "\tdepth = " << minValue[0] << ";\n";
1976
1977 {
1978 uint32_t divider = 2;
1979
1980 // \note Limited to ten bits since the target is 32x32, so there are 10 input bits
1981 for (size_t bitNdx = 0; bitNdx < 10; bitNdx++)
1982 {
1983 fragmentShader << "\tdepth += " << (range[0] / (float)divider) << " * float(bitfieldExtract("
1984 << (bitNdx % 2 == 0 ? "x" : "y") << ", " << (bitNdx / 2) << ", 1));\n";
1985
1986 divider *= 2;
1987 }
1988 }
1989
1990 fragmentShader << "\tgl_FragDepth = depth;\n"
1991 "}\n";
1992
1993 dst.glslSources.add("quad-frag") << glu::FragmentSource(fragmentShader.str());
1994 }
1995 else if (testStencil)
1996 {
1997 dst.glslSources.add("quad-frag")
1998 << glu::FragmentSource("#version 450\n"
1999 "layout(push_constant) uniform PushConstant {\n"
2000 "\thighp uint sampleIndex;\n"
2001 "} pushConstants;\n"
2002 "void main (void)\n"
2003 "{\n"
2004 "\thighp uint sampleIndex = pushConstants.sampleIndex;\n"
2005 "\tgl_SampleMask[0] = int((~0x0u) << sampleIndex);\n"
2006 "}\n");
2007 }
2008 else
2009 {
2010 switch (channelClass)
2011 {
2012 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
2013 {
2014 const UVec4 bits(tcu::getTextureFormatBitDepth(format).cast<uint32_t>());
2015 const UVec4 minValue(0);
2016 const UVec4 range(UVec4(1u) << tcu::min(bits, UVec4(31)));
2017 std::ostringstream fragmentShader;
2018
2019 fragmentShader << "#version 450\n"
2020 "layout(location = 0) out highp uvec4 o_color;\n"
2021 "layout(push_constant) uniform PushConstant {\n"
2022 "\thighp uint sampleIndex;\n"
2023 "} pushConstants;\n"
2024 "void main (void)\n"
2025 "{\n"
2026 "\thighp uint sampleIndex = pushConstants.sampleIndex;\n"
2027 "\tgl_SampleMask[0] = int(0x1u << sampleIndex);\n"
2028 "\thighp uint color[4];\n"
2029 "\thighp uint x = sampleIndex ^ uint(gl_FragCoord.x);\n"
2030 "\thighp uint y = sampleIndex ^ uint(gl_FragCoord.y);\n";
2031
2032 for (int ndx = 0; ndx < 4; ndx++)
2033 fragmentShader << "\tcolor[" << ndx << "] = " << minValue[ndx] << ";\n";
2034
2035 {
2036 const int componentCount = tcu::getNumUsedChannels(format.order);
2037 const uint32_t bitSize(bits[0] + bits[1] + bits[2] + bits[3]);
2038 uint32_t dstBitsUsed[4] = {0u, 0u, 0u, 0u};
2039 uint32_t nextSrcBit = 0;
2040 uint32_t divider = 2;
2041
2042 // \note Limited to ten bits since the target is 32x32, so there are 10 input bits
2043 while (nextSrcBit < de::min(bitSize, 10u))
2044 {
2045 for (int compNdx = 0; compNdx < componentCount; compNdx++)
2046 {
2047 if (dstBitsUsed[compNdx] > bits[compNdx])
2048 continue;
2049
2050 fragmentShader << "\tcolor[" << compNdx << "] += " << (range[compNdx] / divider)
2051 << " * bitfieldExtract(" << (nextSrcBit % 2 == 0 ? "x" : "y") << ", "
2052 << (nextSrcBit / 2) << ", 1);\n";
2053
2054 nextSrcBit++;
2055 dstBitsUsed[compNdx]++;
2056 }
2057
2058 divider *= 2;
2059 }
2060 }
2061
2062 fragmentShader << "\to_color = uvec4(color[0], color[1], color[2], color[3]);\n"
2063 "}\n";
2064
2065 dst.glslSources.add("quad-frag") << glu::FragmentSource(fragmentShader.str());
2066 break;
2067 }
2068
2069 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
2070 {
2071 const UVec4 bits(tcu::getTextureFormatBitDepth(format).cast<uint32_t>());
2072 const IVec4 minValue(0);
2073 const IVec4 range((UVec4(1u) << tcu::min(bits, UVec4(30))).cast<int32_t>());
2074 const IVec4 maxV((UVec4(1u) << (bits - UVec4(1u))).cast<int32_t>());
2075 const IVec4 clampMax(maxV - 1);
2076 const IVec4 clampMin(-maxV);
2077 std::ostringstream fragmentShader;
2078
2079 fragmentShader << "#version 450\n"
2080 "layout(location = 0) out highp ivec4 o_color;\n"
2081 "layout(push_constant) uniform PushConstant {\n"
2082 "\thighp uint sampleIndex;\n"
2083 "} pushConstants;\n"
2084 "void main (void)\n"
2085 "{\n"
2086 "\thighp uint sampleIndex = pushConstants.sampleIndex;\n"
2087 "\tgl_SampleMask[0] = int(0x1u << sampleIndex);\n"
2088 "\thighp int color[4];\n"
2089 "\thighp uint x = sampleIndex ^ uint(gl_FragCoord.x);\n"
2090 "\thighp uint y = sampleIndex ^ uint(gl_FragCoord.y);\n";
2091
2092 for (int ndx = 0; ndx < 4; ndx++)
2093 fragmentShader << "\tcolor[" << ndx << "] = " << minValue[ndx] << ";\n";
2094
2095 {
2096 const int componentCount = tcu::getNumUsedChannels(format.order);
2097 const uint32_t bitSize(bits[0] + bits[1] + bits[2] + bits[3]);
2098 uint32_t dstBitsUsed[4] = {0u, 0u, 0u, 0u};
2099 uint32_t nextSrcBit = 0;
2100 uint32_t divider = 2;
2101
2102 // \note Limited to ten bits since the target is 32x32, so there are 10 input bits
2103 while (nextSrcBit < de::min(bitSize, 10u))
2104 {
2105 for (int compNdx = 0; compNdx < componentCount; compNdx++)
2106 {
2107 if (dstBitsUsed[compNdx] > bits[compNdx])
2108 continue;
2109
2110 fragmentShader << "\tcolor[" << compNdx << "] += " << (range[compNdx] / divider)
2111 << " * int(bitfieldExtract(" << (nextSrcBit % 2 == 0 ? "x" : "y") << ", "
2112 << (nextSrcBit / 2) << ", 1));\n";
2113
2114 nextSrcBit++;
2115 dstBitsUsed[compNdx]++;
2116 }
2117
2118 divider *= 2;
2119 }
2120 }
2121
2122 // The spec doesn't define whether signed-integers are clamped on output,
2123 // so we'll clamp them explicitly to have well-defined outputs.
2124 fragmentShader << "\to_color = clamp(ivec4(color[0], color[1], color[2], color[3]), "
2125 << "ivec4" << clampMin << ", ivec4" << clampMax << ");\n"
2126 << "}\n";
2127
2128 dst.glslSources.add("quad-frag") << glu::FragmentSource(fragmentShader.str());
2129 break;
2130 }
2131
2132 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
2133 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
2134 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
2135 {
2136 const tcu::TextureFormatInfo info(tcu::getTextureFormatInfo(format));
2137 const UVec4 bits(tcu::getTextureFormatMantissaBitDepth(format).cast<uint32_t>());
2138 const Vec4 minLimit(-65536.0);
2139 const Vec4 maxLimit(65536.0);
2140 const Vec4 minValue(tcu::max(info.valueMin, minLimit));
2141 const Vec4 range(tcu::min(info.valueMax, maxLimit) - minValue);
2142 std::ostringstream fragmentShader;
2143
2144 fragmentShader << "#version 450\n"
2145 "layout(location = 0) out highp vec4 o_color;\n"
2146 "layout(push_constant) uniform PushConstant {\n"
2147 "\thighp uint sampleIndex;\n"
2148 "} pushConstants;\n"
2149 "void main (void)\n"
2150 "{\n"
2151 "\thighp uint sampleIndex = pushConstants.sampleIndex;\n"
2152 "\tgl_SampleMask[0] = int(0x1u << sampleIndex);\n"
2153 "\thighp float color[4];\n"
2154 "\thighp uint x = sampleIndex ^ uint(gl_FragCoord.x);\n"
2155 "\thighp uint y = sampleIndex ^ uint(gl_FragCoord.y);\n";
2156
2157 for (int ndx = 0; ndx < 4; ndx++)
2158 fragmentShader << "\tcolor[" << ndx << "] = " << minValue[ndx] << ";\n";
2159
2160 {
2161 const bool isAlphaOnly = isAlphaOnlyFormat(config.format);
2162 const int componentCount = (isAlphaOnly ? 4 : tcu::getNumUsedChannels(format.order));
2163 const uint32_t bitSize(bits[0] + bits[1] + bits[2] + bits[3]);
2164 uint32_t dstBitsUsed[4] = {0u, 0u, 0u, 0u};
2165 uint32_t nextSrcBit = 0;
2166 uint32_t divider = 2;
2167
2168 // \note Limited to ten bits since the target is 32x32, so there are 10 input bits
2169 while (nextSrcBit < de::min(bitSize, 10u))
2170 {
2171 for (int compNdx = 0; compNdx < componentCount; compNdx++)
2172 {
2173 if (dstBitsUsed[compNdx] > bits[compNdx])
2174 continue;
2175
2176 fragmentShader << "\tcolor[" << compNdx << "] += " << (range[compNdx] / (float)divider)
2177 << " * float(bitfieldExtract(" << (nextSrcBit % 2 == 0 ? "x" : "y") << ", "
2178 << (nextSrcBit / 2) << ", 1));\n";
2179
2180 nextSrcBit++;
2181 dstBitsUsed[compNdx]++;
2182 }
2183
2184 divider *= 2;
2185 }
2186 }
2187
2188 fragmentShader << "\to_color = vec4(color[0], color[1], color[2], color[3]);\n"
2189 "}\n";
2190
2191 dst.glslSources.add("quad-frag") << glu::FragmentSource(fragmentShader.str());
2192 break;
2193 }
2194
2195 default:
2196 DE_FATAL("Unknown channel class");
2197 }
2198 }
2199
2200 if (tcu::hasDepthComponent(format.order) || tcu::hasStencilComponent(format.order))
2201 {
2202 std::ostringstream splitShader;
2203
2204 splitShader << "#version 450\n";
2205
2206 if (testDepth && testStencil)
2207 {
2208 splitShader << "layout(input_attachment_index = 0, set = 0, binding = 0) uniform highp subpassInputMS "
2209 "i_depth;\n"
2210 << "layout(input_attachment_index = 0, set = 0, binding = 1) uniform highp usubpassInputMS "
2211 "i_stencil;\n";
2212 }
2213 else if (testDepth)
2214 splitShader << "layout(input_attachment_index = 0, set = 0, binding = 0) uniform highp subpassInputMS "
2215 "i_depth;\n";
2216 else if (testStencil)
2217 splitShader << "layout(input_attachment_index = 0, set = 0, binding = 0) uniform highp usubpassInputMS "
2218 "i_stencil;\n";
2219
2220 splitShader << "layout(push_constant) uniform PushConstant {\n"
2221 "\thighp uint splitSubpassIndex;\n"
2222 "} pushConstants;\n";
2223
2224 for (uint32_t attachmentNdx = 0;
2225 attachmentNdx < de::min((uint32_t)MAX_COLOR_ATTACHMENT_COUNT, config.sampleCount); attachmentNdx++)
2226 {
2227 if (testDepth && testStencil)
2228 splitShader << "layout(location = " << attachmentNdx << ") out highp vec2 o_color" << attachmentNdx
2229 << ";\n";
2230 else
2231 splitShader << "layout(location = " << attachmentNdx << ") out highp float o_color" << attachmentNdx
2232 << ";\n";
2233 }
2234
2235 splitShader << "void main (void)\n"
2236 "{\n";
2237
2238 for (uint32_t attachmentNdx = 0;
2239 attachmentNdx < de::min((uint32_t)MAX_COLOR_ATTACHMENT_COUNT, config.sampleCount); attachmentNdx++)
2240 {
2241 if (testDepth)
2242 splitShader << "\thighp float depth" << attachmentNdx << " = subpassLoad(i_depth, int("
2243 << MAX_COLOR_ATTACHMENT_COUNT << " * pushConstants.splitSubpassIndex + "
2244 << attachmentNdx << "u)).x;\n";
2245
2246 if (testStencil)
2247 splitShader << "\thighp uint stencil" << attachmentNdx << " = subpassLoad(i_stencil, int("
2248 << MAX_COLOR_ATTACHMENT_COUNT << " * pushConstants.splitSubpassIndex + "
2249 << attachmentNdx << "u)).x;\n";
2250
2251 if (testDepth && testStencil)
2252 splitShader << "\to_color" << attachmentNdx << " = vec2(depth" << attachmentNdx << ", float(stencil"
2253 << attachmentNdx << "));\n";
2254 else if (testDepth)
2255 splitShader << "\to_color" << attachmentNdx << " = float(depth" << attachmentNdx << ");\n";
2256 else if (testStencil)
2257 splitShader << "\to_color" << attachmentNdx << " = float(stencil" << attachmentNdx << ");\n";
2258 }
2259
2260 splitShader << "}\n";
2261
2262 dst.glslSources.add("quad-split-frag") << glu::FragmentSource(splitShader.str());
2263 }
2264 else
2265 {
2266 std::string subpassType;
2267 std::string outputType;
2268
2269 switch (channelClass)
2270 {
2271 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
2272 subpassType = "usubpassInputMS";
2273 outputType = "uvec4";
2274 break;
2275
2276 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
2277 subpassType = "isubpassInputMS";
2278 outputType = "ivec4";
2279 break;
2280
2281 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
2282 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
2283 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
2284 subpassType = "subpassInputMS";
2285 outputType = "vec4";
2286 break;
2287
2288 default:
2289 DE_FATAL("Unknown channel class");
2290 }
2291
2292 std::ostringstream splitShader;
2293 splitShader << "#version 450\n"
2294 "layout(input_attachment_index = 0, set = 0, binding = 0) uniform highp "
2295 << subpassType
2296 << " i_color;\n"
2297 "layout(push_constant) uniform PushConstant {\n"
2298 "\thighp uint splitSubpassIndex;\n"
2299 "} pushConstants;\n";
2300
2301 for (uint32_t attachmentNdx = 0;
2302 attachmentNdx < de::min((uint32_t)MAX_COLOR_ATTACHMENT_COUNT, config.sampleCount); attachmentNdx++)
2303 splitShader << "layout(location = " << attachmentNdx << ") out highp " << outputType << " o_color"
2304 << attachmentNdx << ";\n";
2305
2306 splitShader << "void main (void)\n"
2307 "{\n";
2308
2309 for (uint32_t attachmentNdx = 0;
2310 attachmentNdx < de::min((uint32_t)MAX_COLOR_ATTACHMENT_COUNT, config.sampleCount); attachmentNdx++)
2311 splitShader << "\to_color" << attachmentNdx << " = subpassLoad(i_color, int("
2312 << MAX_COLOR_ATTACHMENT_COUNT << " * pushConstants.splitSubpassIndex + " << attachmentNdx
2313 << "u));\n";
2314
2315 splitShader << "}\n";
2316
2317 dst.glslSources.add("quad-split-frag") << glu::FragmentSource(splitShader.str());
2318 }
2319 }
2320 };
2321
checkSupport(Context & context,TestConfig config)2322 void checkSupport(Context &context, TestConfig config)
2323 {
2324 const InstanceInterface &vki = context.getInstanceInterface();
2325 vk::VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
2326
2327 checkPipelineConstructionRequirements(vki, physicalDevice, config.groupParams->pipelineConstructionType);
2328 if (config.groupParams->renderingType == RENDERING_TYPE_RENDERPASS2)
2329 context.requireDeviceFunctionality("VK_KHR_create_renderpass2");
2330
2331 if (config.groupParams->renderingType == RENDERING_TYPE_DYNAMIC_RENDERING)
2332 {
2333 const vk::VkPhysicalDeviceProperties properties = vk::getPhysicalDeviceProperties(vki, physicalDevice);
2334 const uint32_t splitSubpassCount(deDivRoundUp32(config.sampleCount, MAX_COLOR_ATTACHMENT_COUNT));
2335 const tcu::TextureFormat format(mapVkFormat(config.format));
2336 const bool isDepthFormat(tcu::hasDepthComponent(format.order));
2337 const bool isStencilFormat(tcu::hasStencilComponent(format.order));
2338
2339 uint32_t requiredColorAttachmentCount = !(isDepthFormat || isStencilFormat);
2340 for (uint32_t splitSubpassIndex = 0; splitSubpassIndex < splitSubpassCount; splitSubpassIndex++)
2341 requiredColorAttachmentCount +=
2342 de::min((uint32_t)MAX_COLOR_ATTACHMENT_COUNT,
2343 config.sampleCount - splitSubpassIndex * MAX_COLOR_ATTACHMENT_COUNT);
2344
2345 context.requireDeviceFunctionality("VK_KHR_dynamic_rendering_local_read");
2346 if (requiredColorAttachmentCount > properties.limits.maxColorAttachments)
2347 TCU_THROW(NotSupportedError, "Required number of color attachments not supported.");
2348 }
2349
2350 if (config.separateStencilUsage)
2351 {
2352 context.requireDeviceFunctionality("VK_EXT_separate_stencil_usage");
2353 context.requireInstanceFunctionality("VK_KHR_get_physical_device_properties2");
2354 }
2355
2356 #ifndef CTS_USES_VULKANSC
2357 if (config.format == VK_FORMAT_A8_UNORM_KHR)
2358 context.requireDeviceFunctionality("VK_KHR_maintenance5");
2359 #endif // CTS_USES_VULKANSC
2360 }
2361
formatToName(VkFormat format)2362 std::string formatToName(VkFormat format)
2363 {
2364 const std::string formatStr = de::toString(format);
2365 const std::string prefix = "VK_FORMAT_";
2366
2367 DE_ASSERT(formatStr.substr(0, prefix.length()) == prefix);
2368
2369 return de::toLower(formatStr.substr(prefix.length()));
2370 }
2371
initTests(tcu::TestCaseGroup * group,const SharedGroupParams groupParams)2372 void initTests(tcu::TestCaseGroup *group, const SharedGroupParams groupParams)
2373 {
2374 static const VkFormat formats[] = {VK_FORMAT_R5G6B5_UNORM_PACK16,
2375 VK_FORMAT_R8_UNORM,
2376 VK_FORMAT_R8_SNORM,
2377 VK_FORMAT_R8_UINT,
2378 VK_FORMAT_R8_SINT,
2379 VK_FORMAT_R8G8_UNORM,
2380 VK_FORMAT_R8G8_SNORM,
2381 VK_FORMAT_R8G8_UINT,
2382 VK_FORMAT_R8G8_SINT,
2383 #ifndef CTS_USES_VULKANSC
2384 VK_FORMAT_A8_UNORM_KHR,
2385 #endif // CTS_USES_VULKANSC
2386 VK_FORMAT_R8G8B8A8_UNORM,
2387 VK_FORMAT_R8G8B8A8_SNORM,
2388 VK_FORMAT_R8G8B8A8_UINT,
2389 VK_FORMAT_R8G8B8A8_SINT,
2390 VK_FORMAT_R8G8B8A8_SRGB,
2391 VK_FORMAT_A8B8G8R8_UNORM_PACK32,
2392 VK_FORMAT_A8B8G8R8_SNORM_PACK32,
2393 VK_FORMAT_A8B8G8R8_UINT_PACK32,
2394 VK_FORMAT_A8B8G8R8_SINT_PACK32,
2395 VK_FORMAT_A8B8G8R8_SRGB_PACK32,
2396 VK_FORMAT_B8G8R8A8_UNORM,
2397 VK_FORMAT_B8G8R8A8_SRGB,
2398 VK_FORMAT_A2R10G10B10_UNORM_PACK32,
2399 VK_FORMAT_A2B10G10R10_UNORM_PACK32,
2400 VK_FORMAT_A2B10G10R10_UINT_PACK32,
2401 VK_FORMAT_R16_UNORM,
2402 VK_FORMAT_R16_SNORM,
2403 VK_FORMAT_R16_UINT,
2404 VK_FORMAT_R16_SINT,
2405 VK_FORMAT_R16_SFLOAT,
2406 VK_FORMAT_R16G16_UNORM,
2407 VK_FORMAT_R16G16_SNORM,
2408 VK_FORMAT_R16G16_UINT,
2409 VK_FORMAT_R16G16_SINT,
2410 VK_FORMAT_R16G16_SFLOAT,
2411 VK_FORMAT_R16G16B16A16_UNORM,
2412 VK_FORMAT_R16G16B16A16_SNORM,
2413 VK_FORMAT_R16G16B16A16_UINT,
2414 VK_FORMAT_R16G16B16A16_SINT,
2415 VK_FORMAT_R16G16B16A16_SFLOAT,
2416 VK_FORMAT_R32_UINT,
2417 VK_FORMAT_R32_SINT,
2418 VK_FORMAT_R32_SFLOAT,
2419 VK_FORMAT_R32G32_UINT,
2420 VK_FORMAT_R32G32_SINT,
2421 VK_FORMAT_R32G32_SFLOAT,
2422 VK_FORMAT_R32G32B32A32_UINT,
2423 VK_FORMAT_R32G32B32A32_SINT,
2424 VK_FORMAT_R32G32B32A32_SFLOAT,
2425 VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16,
2426
2427 VK_FORMAT_D16_UNORM,
2428 VK_FORMAT_X8_D24_UNORM_PACK32,
2429 VK_FORMAT_D32_SFLOAT,
2430 VK_FORMAT_S8_UINT,
2431 VK_FORMAT_D16_UNORM_S8_UINT,
2432 VK_FORMAT_D24_UNORM_S8_UINT,
2433 VK_FORMAT_D32_SFLOAT_S8_UINT};
2434 const uint32_t sampleCounts[] = {2u, 4u, 8u, 16u, 32u};
2435 tcu::TestContext &testCtx(group->getTestContext());
2436 de::MovePtr<tcu::TestCaseGroup> extGroup(new tcu::TestCaseGroup(testCtx, "separate_stencil_usage"));
2437
2438 for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
2439 {
2440 const VkFormat format(formats[formatNdx]);
2441 const std::string formatName(formatToName(format));
2442 de::MovePtr<tcu::TestCaseGroup> formatGroup(new tcu::TestCaseGroup(testCtx, formatName.c_str()));
2443 de::MovePtr<tcu::TestCaseGroup> extFormatGroup(new tcu::TestCaseGroup(testCtx, formatName.c_str()));
2444
2445 for (size_t sampleCountNdx = 0; sampleCountNdx < DE_LENGTH_OF_ARRAY(sampleCounts); sampleCountNdx++)
2446 {
2447 // limit number of repeated tests for non monolithic pipelines
2448 if ((groupParams->pipelineConstructionType != PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC) &&
2449 (sampleCountNdx > 2))
2450 continue;
2451
2452 const uint32_t sampleCount(sampleCounts[sampleCountNdx]);
2453 const TestConfig testConfig(format, sampleCount, groupParams);
2454 const std::string testName("samples_" + de::toString(sampleCount));
2455
2456 formatGroup->addChild(new InstanceFactory1WithSupport<MultisampleRenderPassTestInstance, TestConfig,
2457 FunctionSupport1<TestConfig>, Programs>(
2458 testCtx, testName.c_str(), testConfig,
2459 typename FunctionSupport1<TestConfig>::Args(checkSupport, testConfig)));
2460
2461 // create tests for VK_EXT_separate_stencil_usage
2462 if (tcu::hasDepthComponent(mapVkFormat(format).order) &&
2463 tcu::hasStencilComponent(mapVkFormat(format).order))
2464 {
2465 de::MovePtr<tcu::TestCaseGroup> sampleGroup(new tcu::TestCaseGroup(testCtx, testName.c_str()));
2466 {
2467 const TestConfig separateUsageDepthTestConfig(format, sampleCount, groupParams, TEST_DEPTH);
2468 sampleGroup->addChild(new InstanceFactory1WithSupport<MultisampleRenderPassTestInstance, TestConfig,
2469 FunctionSupport1<TestConfig>, Programs>(
2470 testCtx, "test_depth", separateUsageDepthTestConfig,
2471 typename FunctionSupport1<TestConfig>::Args(checkSupport, separateUsageDepthTestConfig)));
2472
2473 const TestConfig separateUsageStencilTestConfig(format, sampleCount, groupParams, TEST_STENCIL);
2474 sampleGroup->addChild(new InstanceFactory1WithSupport<MultisampleRenderPassTestInstance, TestConfig,
2475 FunctionSupport1<TestConfig>, Programs>(
2476 testCtx, "test_stencil", separateUsageStencilTestConfig,
2477 typename FunctionSupport1<TestConfig>::Args(checkSupport, separateUsageStencilTestConfig)));
2478 }
2479
2480 extFormatGroup->addChild(sampleGroup.release());
2481 }
2482 }
2483
2484 group->addChild(formatGroup.release());
2485 extGroup->addChild(extFormatGroup.release());
2486 }
2487
2488 group->addChild(extGroup.release());
2489 }
2490
2491 } // namespace
2492
createRenderPassMultisampleTests(tcu::TestContext & testCtx,const SharedGroupParams groupParams)2493 tcu::TestCaseGroup *createRenderPassMultisampleTests(tcu::TestContext &testCtx, const SharedGroupParams groupParams)
2494 {
2495 return createTestGroup(testCtx, "multisample", initTests, groupParams);
2496 }
2497
2498 } // namespace renderpass
2499
2500 } // namespace vkt
2501