1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2021 Valve Corporation.
6 * Copyright (c) 2023 LunarG, Inc.
7 * Copyright (c) 2023 Nintendo
8 *
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 * http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 *
21 *//*!
22 * \file
23 * \brief VK_EXT_attachment_feedback_loop_layout Tests
24 *//*--------------------------------------------------------------------*/
25
26 #include "vktPipelineAttachmentFeedbackLoopLayoutTests.hpp"
27 #include "vktPipelineImageSamplingInstance.hpp"
28 #include "vktPipelineImageUtil.hpp"
29 #include "vktPipelineVertexUtil.hpp"
30 #include "vktTestCase.hpp"
31 #include "vktPipelineClearUtil.hpp"
32
33 #include "vkImageUtil.hpp"
34 #include "vkQueryUtil.hpp"
35 #include "vkTypeUtil.hpp"
36 #include "vkObjUtil.hpp"
37 #include "vkBuilderUtil.hpp"
38 #include "vkBarrierUtil.hpp"
39 #include "vkCmdUtil.hpp"
40 #include "vkPrograms.hpp"
41 #include "vkImageWithMemory.hpp"
42 #include "vkBufferWithMemory.hpp"
43
44 #include "tcuPlatform.hpp"
45 #include "tcuImageCompare.hpp"
46 #include "tcuTextureUtil.hpp"
47 #include "tcuTestLog.hpp"
48 #include "tcuMaybe.hpp"
49
50 #include "deStringUtil.hpp"
51 #include "deMemory.h"
52
53 #include <iomanip>
54 #include <sstream>
55 #include <vector>
56 #include <string>
57 #include <memory>
58 #include <utility>
59 #include <algorithm>
60
61 namespace vkt
62 {
63 namespace pipeline
64 {
65
66 using namespace vk;
67 using de::MovePtr;
68
69 namespace
70 {
71
72 enum TestMode
73 {
74 TEST_MODE_READ_ONLY = 0,
75 TEST_MODE_WRITE_ONLY = 1,
76 TEST_MODE_READ_WRITE_SAME_PIXEL = 2, // Sample from and write to the same pixel
77 TEST_MODE_READ_WRITE_DIFFERENT_AREAS =
78 3, // Sample from one half of the image and write the values to the other half
79 };
80
81 enum ImageAspectTestMode
82 {
83 IMAGE_ASPECT_TEST_COLOR = 0,
84 IMAGE_ASPECT_TEST_DEPTH = 1,
85 IMAGE_ASPECT_TEST_STENCIL = 2,
86 };
87
testModeToAspectFlags(ImageAspectTestMode testMode)88 VkImageAspectFlagBits testModeToAspectFlags(ImageAspectTestMode testMode)
89 {
90 switch (testMode)
91 {
92 case IMAGE_ASPECT_TEST_COLOR:
93 return VK_IMAGE_ASPECT_COLOR_BIT;
94 case IMAGE_ASPECT_TEST_DEPTH:
95 return VK_IMAGE_ASPECT_DEPTH_BIT;
96 case IMAGE_ASPECT_TEST_STENCIL:
97 return VK_IMAGE_ASPECT_STENCIL_BIT;
98 default:
99 break;
100 }
101
102 DE_ASSERT(false);
103 return VK_IMAGE_ASPECT_FLAG_BITS_MAX_ENUM;
104 }
105
106 enum class PipelineStateMode
107 {
108 STATIC = 0, // Static only.
109 DYNAMIC_WITH_ZERO_STATIC, // Dynamic, with static flags 0.
110 DYNAMIC_WITH_CONTRADICTORY_STATIC, // Dynamic, with static flags contradicting the dynamic state (see below).
111 };
112
aspectFlagsToPipelineCreateFlags(VkImageAspectFlags aspectFlags)113 VkPipelineCreateFlags aspectFlagsToPipelineCreateFlags(VkImageAspectFlags aspectFlags)
114 {
115 VkPipelineCreateFlags pipelineFlags = 0u;
116
117 if ((aspectFlags & VK_IMAGE_ASPECT_COLOR_BIT) != 0u)
118 pipelineFlags |= VK_PIPELINE_CREATE_COLOR_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT;
119
120 if ((aspectFlags & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) != 0u)
121 pipelineFlags |= VK_PIPELINE_CREATE_DEPTH_STENCIL_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT;
122
123 return pipelineFlags;
124 }
125
getStaticPipelineCreateFlags(VkImageAspectFlags usedFlags,PipelineStateMode stateMode)126 VkPipelineCreateFlags getStaticPipelineCreateFlags(VkImageAspectFlags usedFlags, PipelineStateMode stateMode)
127 {
128 if (stateMode == PipelineStateMode::STATIC)
129 return aspectFlagsToPipelineCreateFlags(usedFlags);
130
131 if (stateMode == PipelineStateMode::DYNAMIC_WITH_ZERO_STATIC)
132 return 0u;
133
134 // Statically include all flags which are not present in the used flags that will be set dynamically.
135 VkPipelineCreateFlags pipelineStaticFlags = (VK_PIPELINE_CREATE_COLOR_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT |
136 VK_PIPELINE_CREATE_DEPTH_STENCIL_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT);
137 VkPipelineCreateFlags pipelineUsedFlags = aspectFlagsToPipelineCreateFlags(usedFlags);
138
139 pipelineStaticFlags &= (~pipelineUsedFlags);
140 return pipelineStaticFlags;
141 }
142
143 // Output images are a square of this size
144 const int outputImageSize = 256;
145
getImageAspectTestMode(const VkFormat format)146 ImageAspectTestMode getImageAspectTestMode(const VkFormat format)
147 {
148 if (tcu::hasDepthComponent(mapVkFormat(format).order))
149 return IMAGE_ASPECT_TEST_DEPTH;
150
151 if (tcu::hasStencilComponent(mapVkFormat(format).order))
152 return IMAGE_ASPECT_TEST_STENCIL;
153
154 return IMAGE_ASPECT_TEST_COLOR;
155 };
156
157 class SamplerViewType
158 {
159 public:
SamplerViewType(vk::VkImageViewType type,bool normalized=true)160 SamplerViewType(vk::VkImageViewType type, bool normalized = true) : m_viewType(type), m_normalized(normalized)
161 {
162 if (!normalized)
163 DE_ASSERT(type == vk::VK_IMAGE_VIEW_TYPE_2D || type == vk::VK_IMAGE_VIEW_TYPE_1D);
164 }
165
operator vk::VkImageViewType() const166 operator vk::VkImageViewType() const
167 {
168 return m_viewType;
169 }
170
isNormalized() const171 bool isNormalized() const
172 {
173 return m_normalized;
174 }
175
176 private:
177 vk::VkImageViewType m_viewType;
178 bool m_normalized;
179 };
180
allocateImage(const InstanceInterface & vki,const DeviceInterface & vkd,const VkPhysicalDevice & physDevice,const VkDevice device,const VkImage & image,const MemoryRequirement requirement,Allocator & allocator,AllocationKind allocationKind)181 de::MovePtr<Allocation> allocateImage(const InstanceInterface &vki, const DeviceInterface &vkd,
182 const VkPhysicalDevice &physDevice, const VkDevice device, const VkImage &image,
183 const MemoryRequirement requirement, Allocator &allocator,
184 AllocationKind allocationKind)
185 {
186 switch (allocationKind)
187 {
188 case ALLOCATION_KIND_SUBALLOCATED:
189 {
190 const VkMemoryRequirements memoryRequirements = getImageMemoryRequirements(vkd, device, image);
191
192 return allocator.allocate(memoryRequirements, requirement);
193 }
194
195 case ALLOCATION_KIND_DEDICATED:
196 {
197 return allocateDedicated(vki, vkd, physDevice, device, image, requirement);
198 }
199
200 default:
201 {
202 TCU_THROW(InternalError, "Invalid allocation kind");
203 }
204 }
205 }
206
allocateBuffer(const InstanceInterface & vki,const DeviceInterface & vkd,const VkPhysicalDevice & physDevice,const VkDevice device,const VkBuffer & buffer,const MemoryRequirement requirement,Allocator & allocator,AllocationKind allocationKind)207 de::MovePtr<Allocation> allocateBuffer(const InstanceInterface &vki, const DeviceInterface &vkd,
208 const VkPhysicalDevice &physDevice, const VkDevice device,
209 const VkBuffer &buffer, const MemoryRequirement requirement,
210 Allocator &allocator, AllocationKind allocationKind)
211 {
212 switch (allocationKind)
213 {
214 case ALLOCATION_KIND_SUBALLOCATED:
215 {
216 const VkMemoryRequirements memoryRequirements = getBufferMemoryRequirements(vkd, device, buffer);
217
218 return allocator.allocate(memoryRequirements, requirement);
219 }
220
221 case ALLOCATION_KIND_DEDICATED:
222 {
223 return allocateDedicated(vki, vkd, physDevice, device, buffer, requirement);
224 }
225
226 default:
227 {
228 TCU_THROW(InternalError, "Invalid allocation kind");
229 }
230 }
231 }
232
getCompatibleImageType(VkImageViewType viewType)233 static VkImageType getCompatibleImageType(VkImageViewType viewType)
234 {
235 switch (viewType)
236 {
237 case VK_IMAGE_VIEW_TYPE_1D:
238 return VK_IMAGE_TYPE_1D;
239 case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
240 return VK_IMAGE_TYPE_1D;
241 case VK_IMAGE_VIEW_TYPE_2D:
242 return VK_IMAGE_TYPE_2D;
243 case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
244 return VK_IMAGE_TYPE_2D;
245 case VK_IMAGE_VIEW_TYPE_3D:
246 return VK_IMAGE_TYPE_3D;
247 case VK_IMAGE_VIEW_TYPE_CUBE:
248 return VK_IMAGE_TYPE_2D;
249 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
250 return VK_IMAGE_TYPE_2D;
251 default:
252 break;
253 }
254
255 DE_ASSERT(false);
256 return VK_IMAGE_TYPE_1D;
257 }
258
259 template <typename TcuFormatType>
createTestTexture(const TcuFormatType format,VkImageViewType viewType,const tcu::IVec3 & size,int layerCount)260 static MovePtr<TestTexture> createTestTexture(const TcuFormatType format, VkImageViewType viewType,
261 const tcu::IVec3 &size, int layerCount)
262 {
263 MovePtr<TestTexture> texture;
264 const VkImageType imageType = getCompatibleImageType(viewType);
265
266 switch (imageType)
267 {
268 case VK_IMAGE_TYPE_1D:
269 if (layerCount == 1)
270 texture = MovePtr<TestTexture>(new TestTexture1D(format, size.x()));
271 else
272 texture = MovePtr<TestTexture>(new TestTexture1DArray(format, size.x(), layerCount));
273
274 break;
275
276 case VK_IMAGE_TYPE_2D:
277 if (layerCount == 1)
278 {
279 texture = MovePtr<TestTexture>(new TestTexture2D(format, size.x(), size.y()));
280 }
281 else
282 {
283 if (viewType == VK_IMAGE_VIEW_TYPE_CUBE || viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
284 {
285 if (layerCount == tcu::CUBEFACE_LAST && viewType == VK_IMAGE_VIEW_TYPE_CUBE)
286 {
287 texture = MovePtr<TestTexture>(new TestTextureCube(format, size.x()));
288 }
289 else
290 {
291 DE_ASSERT(layerCount % tcu::CUBEFACE_LAST == 0);
292
293 texture = MovePtr<TestTexture>(new TestTextureCubeArray(format, size.x(), layerCount));
294 }
295 }
296 else
297 {
298 texture = MovePtr<TestTexture>(new TestTexture2DArray(format, size.x(), size.y(), layerCount));
299 }
300 }
301
302 break;
303
304 case VK_IMAGE_TYPE_3D:
305 texture = MovePtr<TestTexture>(new TestTexture3D(format, size.x(), size.y(), size.z()));
306 break;
307
308 default:
309 DE_ASSERT(false);
310 }
311
312 return texture;
313 }
314
getAspectFlags(tcu::TextureFormat format)315 VkImageAspectFlags getAspectFlags(tcu::TextureFormat format)
316 {
317 VkImageAspectFlags aspectFlag = 0;
318 aspectFlag |= (tcu::hasDepthComponent(format.order) ? VK_IMAGE_ASPECT_DEPTH_BIT : 0);
319 aspectFlag |= (tcu::hasStencilComponent(format.order) ? VK_IMAGE_ASPECT_STENCIL_BIT : 0);
320
321 if (!aspectFlag)
322 aspectFlag = VK_IMAGE_ASPECT_COLOR_BIT;
323
324 return aspectFlag;
325 }
326
getAspectFlags(VkFormat format)327 VkImageAspectFlags getAspectFlags(VkFormat format)
328 {
329 if (isCompressedFormat(format))
330 return VK_IMAGE_ASPECT_COLOR_BIT;
331 else
332 return getAspectFlags(mapVkFormat(format));
333 }
334
getSizeCompatibleTcuTextureFormat(VkFormat format)335 tcu::TextureFormat getSizeCompatibleTcuTextureFormat(VkFormat format)
336 {
337 if (isCompressedFormat(format))
338 return (getBlockSizeInBytes(format) == 8) ? mapVkFormat(VK_FORMAT_R16G16B16A16_UINT) :
339 mapVkFormat(VK_FORMAT_R32G32B32A32_UINT);
340 else
341 return mapVkFormat(format);
342 }
343
344 // Utilities to create test nodes
getFormatCaseName(const VkFormat format)345 std::string getFormatCaseName(const VkFormat format)
346 {
347 const std::string fullName = getFormatName(format);
348
349 DE_ASSERT(de::beginsWith(fullName, "VK_FORMAT_"));
350
351 return de::toLower(fullName.substr(10));
352 }
353
354 class AttachmentFeedbackLoopLayoutImageSamplingInstance : public ImageSamplingInstance
355 {
356 public:
357 AttachmentFeedbackLoopLayoutImageSamplingInstance(Context &context, ImageSamplingInstanceParams params,
358 bool useImageAsColorOrDSAttachment_,
359 bool useDifferentAreasSampleWrite_,
360 bool interleaveReadWriteComponents_,
361 ImageAspectTestMode imageAspectTestMode,
362 PipelineStateMode pipelineStateMode, bool useMaintenance5_);
363
364 virtual ~AttachmentFeedbackLoopLayoutImageSamplingInstance(void);
365
366 virtual tcu::TestStatus iterate(void) override;
367
368 protected:
369 virtual tcu::TestStatus verifyImage(void) override;
370 virtual void setup(void) override;
371
372 ImageSamplingInstanceParams m_params;
373 const bool m_useImageAsColorOrDSAttachment;
374 const bool m_useDifferentAreasSampleWrite;
375 const bool m_interleaveReadWriteComponents;
376 const ImageAspectTestMode m_imageAspectTestMode;
377 const PipelineStateMode m_pipelineStateMode;
378 const bool m_useMaintenance5;
379 };
380
381 class AttachmentFeedbackLoopLayoutDepthStencilImageSamplingInstance
382 : public AttachmentFeedbackLoopLayoutImageSamplingInstance
383 {
384 public:
385 AttachmentFeedbackLoopLayoutDepthStencilImageSamplingInstance(
386 Context &context, ImageSamplingInstanceParams params, bool useImageAsColorOrDSAttachment_,
387 bool useDifferentAreasSampleWrite_, bool interleaveReadWriteComponents_,
388 ImageAspectTestMode imageAspectTestMode, PipelineStateMode pipelineStateMode, bool useMaintenance5_);
389
390 virtual ~AttachmentFeedbackLoopLayoutDepthStencilImageSamplingInstance(void);
391
392 virtual tcu::TestStatus iterate(void) override;
393
394 protected:
395 virtual tcu::TestStatus verifyImage(void) override;
396 virtual void setup(void) override;
397
398 bool m_separateStencilUsage;
399
400 std::vector<SharedImagePtr> m_dsImages;
401 std::vector<SharedAllocPtr> m_dsImageAllocs;
402 std::vector<SharedImageViewPtr> m_dsAttachmentViews;
403 };
404
AttachmentFeedbackLoopLayoutImageSamplingInstance(Context & context,ImageSamplingInstanceParams params,bool useImageAsColorOrDSAttachment_,bool useDifferentAreasSampleWrite_,bool interleaveReadWriteComponents_,ImageAspectTestMode imageAspectTestMode,PipelineStateMode pipelineStateMode,bool useMaintenance5_)405 AttachmentFeedbackLoopLayoutImageSamplingInstance::AttachmentFeedbackLoopLayoutImageSamplingInstance(
406 Context &context, ImageSamplingInstanceParams params, bool useImageAsColorOrDSAttachment_,
407 bool useDifferentAreasSampleWrite_, bool interleaveReadWriteComponents_, ImageAspectTestMode imageAspectTestMode,
408 PipelineStateMode pipelineStateMode, bool useMaintenance5_)
409 : ImageSamplingInstance(context, params)
410 , m_params(params)
411 , m_useImageAsColorOrDSAttachment(useImageAsColorOrDSAttachment_)
412 , m_useDifferentAreasSampleWrite(useDifferentAreasSampleWrite_)
413 , m_interleaveReadWriteComponents(interleaveReadWriteComponents_)
414 , m_imageAspectTestMode(imageAspectTestMode)
415 , m_pipelineStateMode(pipelineStateMode)
416 , m_useMaintenance5(useMaintenance5_)
417 {
418 }
419
setup(void)420 void AttachmentFeedbackLoopLayoutImageSamplingInstance::setup(void)
421 {
422 const InstanceInterface &vki = m_context.getInstanceInterface();
423 const DeviceInterface &vk = m_context.getDeviceInterface();
424 const VkPhysicalDevice physDevice = m_context.getPhysicalDevice();
425 const VkDevice vkDevice = m_context.getDevice();
426 const VkQueue queue = m_context.getUniversalQueue();
427 const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
428 SimpleAllocator memAlloc(
429 vk, vkDevice,
430 getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
431 const VkComponentMapping componentMappingRGBA = {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G,
432 VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A};
433 tcu::UVec2 renderSize = m_useImageAsColorOrDSAttachment ?
434 tcu::UVec2({(unsigned)m_imageSize.x(), (unsigned)m_imageSize.y()}) :
435 m_renderSize;
436
437 DE_ASSERT(m_samplerParams.pNext == DE_NULL);
438
439 // Create texture images, views and samplers
440 {
441 VkImageCreateFlags imageFlags = 0u;
442
443 if (m_imageViewType == VK_IMAGE_VIEW_TYPE_CUBE || m_imageViewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
444 imageFlags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
445
446 // Initialize texture data
447 if (isCompressedFormat(m_imageFormat))
448 m_texture =
449 createTestTexture(mapVkCompressedFormat(m_imageFormat), m_imageViewType, m_imageSize, m_layerCount);
450 else
451 m_texture = createTestTexture(mapVkFormat(m_imageFormat), m_imageViewType, m_imageSize, m_layerCount);
452
453 VkImageUsageFlags imageUsageFlags = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
454 VK_IMAGE_USAGE_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT |
455 VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
456
457 if (isDepthStencilFormat(m_imageFormat))
458 imageUsageFlags |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
459 else
460 imageUsageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
461
462 const VkImageCreateInfo imageParams = {
463 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
464 DE_NULL, // const void* pNext;
465 imageFlags, // VkImageCreateFlags flags;
466 getCompatibleImageType(m_imageViewType), // VkImageType imageType;
467 m_imageFormat, // VkFormat format;
468 { // VkExtent3D extent;
469 (uint32_t)m_imageSize.x(), (uint32_t)m_imageSize.y(), (uint32_t)m_imageSize.z()},
470 (uint32_t)m_texture->getNumLevels(), // uint32_t mipLevels;
471 (uint32_t)m_layerCount, // uint32_t arrayLayers;
472 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
473 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
474 imageUsageFlags, // VkImageUsageFlags usage;
475 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
476 1u, // uint32_t queueFamilyIndexCount;
477 &queueFamilyIndex, // const uint32_t* pQueueFamilyIndices;
478 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
479 };
480
481 checkImageSupport(vki, physDevice, imageParams);
482
483 m_images.resize(m_imageCount);
484 m_imageAllocs.resize(m_imageCount);
485 m_imageViews.resize(m_imageCount);
486
487 // Create command pool
488 m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
489 m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
490
491 for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
492 {
493 m_images[imgNdx] = SharedImagePtr(new UniqueImage(createImage(vk, vkDevice, &imageParams)));
494 m_imageAllocs[imgNdx] =
495 SharedAllocPtr(new UniqueAlloc(allocateImage(vki, vk, physDevice, vkDevice, **m_images[imgNdx],
496 MemoryRequirement::Any, memAlloc, m_allocationKind)));
497 VK_CHECK(vk.bindImageMemory(vkDevice, **m_images[imgNdx], (*m_imageAllocs[imgNdx])->getMemory(),
498 (*m_imageAllocs[imgNdx])->getOffset()));
499
500 // Upload texture data
501 uploadTestTexture(vk, vkDevice, queue, queueFamilyIndex, memAlloc, *m_texture, **m_images[imgNdx],
502 m_imageLayout);
503
504 // Create image view and sampler
505 const VkImageViewCreateInfo imageViewParams = {
506 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
507 DE_NULL, // const void* pNext;
508 0u, // VkImageViewCreateFlags flags;
509 **m_images[imgNdx], // VkImage image;
510 m_imageViewType, // VkImageViewType viewType;
511 m_imageFormat, // VkFormat format;
512 m_componentMapping, // VkComponentMapping components;
513 m_subresourceRange, // VkImageSubresourceRange subresourceRange;
514 };
515
516 m_imageViews[imgNdx] =
517 SharedImageViewPtr(new UniqueImageView(createImageView(vk, vkDevice, &imageViewParams)));
518 }
519
520 m_sampler = createSampler(vk, vkDevice, &m_samplerParams);
521 }
522
523 // Create descriptor set for image and sampler
524 {
525 DescriptorPoolBuilder descriptorPoolBuilder;
526 if (m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
527 descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_SAMPLER, 1u);
528 descriptorPoolBuilder.addType(m_samplingType, m_imageCount);
529 m_descriptorPool = descriptorPoolBuilder.build(
530 vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
531 m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ? m_imageCount + 1u : m_imageCount);
532
533 DescriptorSetLayoutBuilder setLayoutBuilder;
534 if (m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
535 setLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT);
536 setLayoutBuilder.addArrayBinding(m_samplingType, m_imageCount, VK_SHADER_STAGE_FRAGMENT_BIT);
537 m_descriptorSetLayout = setLayoutBuilder.build(vk, vkDevice);
538
539 const VkDescriptorSetAllocateInfo descriptorSetAllocateInfo = {
540 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // VkStructureType sType;
541 DE_NULL, // const void* pNext;
542 *m_descriptorPool, // VkDescriptorPool descriptorPool;
543 1u, // uint32_t setLayoutCount;
544 &m_descriptorSetLayout.get() // const VkDescriptorSetLayout* pSetLayouts;
545 };
546
547 m_descriptorSet = allocateDescriptorSet(vk, vkDevice, &descriptorSetAllocateInfo);
548
549 const VkSampler sampler = m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ? DE_NULL : *m_sampler;
550 std::vector<VkDescriptorImageInfo> descriptorImageInfo(m_imageCount);
551 for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
552 {
553 descriptorImageInfo[imgNdx].sampler = sampler; // VkSampler sampler;
554 descriptorImageInfo[imgNdx].imageView = **m_imageViews[imgNdx]; // VkImageView imageView;
555 descriptorImageInfo[imgNdx].imageLayout = m_imageLayout; // VkImageLayout imageLayout;
556 }
557
558 DescriptorSetUpdateBuilder setUpdateBuilder;
559 if (m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
560 {
561 const VkDescriptorImageInfo descriptorSamplerInfo = {
562 *m_sampler, // VkSampler sampler;
563 DE_NULL, // VkImageView imageView;
564 m_imageLayout, // VkImageLayout imageLayout;
565 };
566 setUpdateBuilder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0),
567 VK_DESCRIPTOR_TYPE_SAMPLER, &descriptorSamplerInfo);
568 }
569
570 const uint32_t binding = m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ? 1u : 0u;
571 setUpdateBuilder.writeArray(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(binding),
572 m_samplingType, m_imageCount, descriptorImageInfo.data());
573 setUpdateBuilder.update(vk, vkDevice);
574 }
575
576 // Create color images and views
577 {
578 const VkImageCreateInfo colorImageParams = {
579 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
580 DE_NULL, // const void* pNext;
581 0u, // VkImageCreateFlags flags;
582 VK_IMAGE_TYPE_2D, // VkImageType imageType;
583 m_colorFormat, // VkFormat format;
584 {(uint32_t)renderSize.x(), (uint32_t)renderSize.y(), 1u}, // VkExtent3D extent;
585 1u, // uint32_t mipLevels;
586 1u, // uint32_t arrayLayers;
587 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
588 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
589 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage;
590 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
591 1u, // uint32_t queueFamilyIndexCount;
592 &queueFamilyIndex, // const uint32_t* pQueueFamilyIndices;
593 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
594 };
595
596 checkImageSupport(vki, physDevice, colorImageParams);
597
598 m_colorImages.resize(m_imageCount);
599 m_colorImageAllocs.resize(m_imageCount);
600 m_colorAttachmentViews.resize(m_imageCount);
601
602 if (m_useImageAsColorOrDSAttachment)
603 {
604 for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
605 {
606 m_colorImages[imgNdx] = m_images[imgNdx];
607 m_colorImageAllocs[imgNdx] = m_imageAllocs[imgNdx];
608 m_colorAttachmentViews[imgNdx] = m_imageViews[imgNdx];
609 }
610 }
611 else
612 {
613 for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
614 {
615 m_colorImages[imgNdx] = SharedImagePtr(new UniqueImage(createImage(vk, vkDevice, &colorImageParams)));
616 m_colorImageAllocs[imgNdx] =
617 SharedAllocPtr(new UniqueAlloc(allocateImage(vki, vk, physDevice, vkDevice, **m_colorImages[imgNdx],
618 MemoryRequirement::Any, memAlloc, m_allocationKind)));
619 VK_CHECK(vk.bindImageMemory(vkDevice, **m_colorImages[imgNdx],
620 (*m_colorImageAllocs[imgNdx])->getMemory(),
621 (*m_colorImageAllocs[imgNdx])->getOffset()));
622
623 const VkImageViewCreateInfo colorAttachmentViewParams = {
624 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
625 DE_NULL, // const void* pNext;
626 0u, // VkImageViewCreateFlags flags;
627 **m_colorImages[imgNdx], // VkImage image;
628 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
629 m_colorFormat, // VkFormat format;
630 componentMappingRGBA, // VkComponentMapping components;
631 {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u} // VkImageSubresourceRange subresourceRange;
632 };
633
634 m_colorAttachmentViews[imgNdx] =
635 SharedImageViewPtr(new UniqueImageView(createImageView(vk, vkDevice, &colorAttachmentViewParams)));
636 }
637 }
638 }
639
640 // Create render pass
641 {
642 std::vector<VkAttachmentDescription> attachmentDescriptions(m_imageCount);
643 std::vector<VkAttachmentReference> attachmentReferences(m_imageCount);
644
645 VkAttachmentLoadOp loadOp =
646 m_useImageAsColorOrDSAttachment ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_CLEAR;
647 VkImageLayout imageLayout =
648 m_useImageAsColorOrDSAttachment ? m_imageLayout : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
649
650 for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
651 {
652 attachmentDescriptions[imgNdx].flags = 0u; // VkAttachmentDescriptionFlags flags;
653 attachmentDescriptions[imgNdx].format =
654 m_useImageAsColorOrDSAttachment ? m_imageFormat : m_colorFormat; // VkFormat format;
655 attachmentDescriptions[imgNdx].samples = VK_SAMPLE_COUNT_1_BIT; // VkSampleCountFlagBits samples;
656 attachmentDescriptions[imgNdx].loadOp = loadOp; // VkAttachmentLoadOp loadOp;
657 attachmentDescriptions[imgNdx].storeOp = VK_ATTACHMENT_STORE_OP_STORE; // VkAttachmentStoreOp storeOp;
658 attachmentDescriptions[imgNdx].stencilLoadOp = loadOp; // VkAttachmentLoadOp stencilLoadOp;
659 attachmentDescriptions[imgNdx].stencilStoreOp =
660 VK_ATTACHMENT_STORE_OP_STORE; // VkAttachmentStoreOp stencilStoreOp;
661 attachmentDescriptions[imgNdx].initialLayout = imageLayout; // VkImageLayout initialLayout;
662 attachmentDescriptions[imgNdx].finalLayout = imageLayout; // VkImageLayout finalLayout;
663
664 attachmentReferences[imgNdx].attachment = (uint32_t)imgNdx; // uint32_t attachment;
665 attachmentReferences[imgNdx].layout = imageLayout; // VkImageLayout layout;
666 }
667
668 const VkSubpassDescription subpassDescription = {
669 0u, // VkSubpassDescriptionFlags flags;
670 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
671 0u, // uint32_t inputAttachmentCount;
672 DE_NULL, // const VkAttachmentReference* pInputAttachments;
673 (uint32_t)m_imageCount, // uint32_t colorAttachmentCount;
674 &attachmentReferences[0], // const VkAttachmentReference* pColorAttachments;
675 DE_NULL, // const VkAttachmentReference* pResolveAttachments;
676 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment;
677 0u, // uint32_t preserveAttachmentCount;
678 DE_NULL // const VkAttachmentReference* pPreserveAttachments;
679 };
680
681 std::vector<VkSubpassDependency> subpassDependencies;
682
683 if (m_useImageAsColorOrDSAttachment)
684 {
685 const VkSubpassDependency spdVal = {
686 0u, // uint32_t srcSubpass;
687 0u, // uint32_t dstSubpass;
688 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, // VkPipelineStageFlags srcStageMask;
689 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, // VkPipelineStageFlags dstStageMask;
690 VK_ACCESS_SHADER_READ_BIT, // VkAccessFlags srcAccessMask;
691 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask;
692 VK_DEPENDENCY_FEEDBACK_LOOP_BIT_EXT | VK_DEPENDENCY_BY_REGION_BIT, // VkDependencyFlags dependencyFlags;
693 };
694
695 subpassDependencies.push_back(spdVal);
696 }
697
698 const VkRenderPassCreateInfo renderPassParams = {
699 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
700 DE_NULL, // const void* pNext;
701 0u, // VkRenderPassCreateFlags flags;
702 (uint32_t)attachmentDescriptions.size(), // uint32_t attachmentCount;
703 &attachmentDescriptions[0], // const VkAttachmentDescription* pAttachments;
704 1u, // uint32_t subpassCount;
705 &subpassDescription, // const VkSubpassDescription* pSubpasses;
706 static_cast<uint32_t>(subpassDependencies.size()), // uint32_t dependencyCount;
707 de::dataOrNull(subpassDependencies), // const VkSubpassDependency* pDependencies;
708 };
709
710 m_renderPass = RenderPassWrapper(m_pipelineConstructionType, vk, vkDevice, &renderPassParams);
711 }
712
713 // Create framebuffer
714 {
715 std::vector<VkImage> images(m_imageCount);
716 std::vector<VkImageView> pAttachments(m_imageCount);
717 for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
718 {
719 images[imgNdx] = m_colorImages[imgNdx]->get();
720 pAttachments[imgNdx] = m_colorAttachmentViews[imgNdx]->get();
721 }
722
723 const VkFramebufferCreateInfo framebufferParams = {
724 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
725 DE_NULL, // const void* pNext;
726 0u, // VkFramebufferCreateFlags flags;
727 *m_renderPass, // VkRenderPass renderPass;
728 (uint32_t)m_imageCount, // uint32_t attachmentCount;
729 &pAttachments[0], // const VkImageView* pAttachments;
730 (uint32_t)renderSize.x(), // uint32_t width;
731 (uint32_t)renderSize.y(), // uint32_t height;
732 1u // uint32_t layers;
733 };
734
735 m_renderPass.createFramebuffer(vk, vkDevice, &framebufferParams, images);
736 }
737
738 // Create pipeline layouts
739 {
740 const VkPipelineLayoutCreateInfo pipelineLayoutParams = {
741 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
742 DE_NULL, // const void* pNext;
743 VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT, // VkPipelineLayoutCreateFlags flags;
744 0u, // uint32_t setLayoutCount;
745 DE_NULL, // const VkDescriptorSetLayout* pSetLayouts;
746 0u, // uint32_t pushConstantRangeCount;
747 DE_NULL // const VkPushConstantRange* pPushConstantRanges;
748 };
749
750 m_preRasterizationStatePipelineLayout =
751 PipelineLayoutWrapper(m_pipelineConstructionType, vk, vkDevice, &pipelineLayoutParams);
752 }
753 {
754 const VkPipelineLayoutCreateInfo pipelineLayoutParams = {
755 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
756 DE_NULL, // const void* pNext;
757 VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT, // VkPipelineLayoutCreateFlags flags;
758 1u, // uint32_t setLayoutCount;
759 &m_descriptorSetLayout.get(), // const VkDescriptorSetLayout* pSetLayouts;
760 0u, // uint32_t pushConstantRangeCount;
761 DE_NULL // const VkPushConstantRange* pPushConstantRanges;
762 };
763
764 m_fragmentStatePipelineLayout =
765 PipelineLayoutWrapper(m_pipelineConstructionType, vk, vkDevice, &pipelineLayoutParams);
766 }
767
768 m_vertexShaderModule = ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("tex_vert"), 0);
769 m_fragmentShaderModule = ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("tex_frag"), 0);
770
771 // Create pipeline
772 {
773 const VkVertexInputBindingDescription vertexInputBindingDescription = {
774 0u, // uint32_t binding;
775 sizeof(Vertex4Tex4), // uint32_t strideInBytes;
776 VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputStepRate inputRate;
777 };
778
779 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] = {
780 {
781 0u, // uint32_t location;
782 0u, // uint32_t binding;
783 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
784 0u // uint32_t offset;
785 },
786 {
787 1u, // uint32_t location;
788 0u, // uint32_t binding;
789 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
790 offsetof(Vertex4Tex4, texCoord), // uint32_t offset;
791 }};
792
793 const VkPipelineVertexInputStateCreateInfo vertexInputStateParams = {
794 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
795 DE_NULL, // const void* pNext;
796 0u, // VkPipelineVertexInputStateCreateFlags flags;
797 1u, // uint32_t vertexBindingDescriptionCount;
798 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
799 2u, // uint32_t vertexAttributeDescriptionCount;
800 vertexInputAttributeDescriptions // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
801 };
802
803 const std::vector<VkViewport> viewports(1, makeViewport(renderSize));
804 const std::vector<VkRect2D> scissors(1, makeRect2D(renderSize));
805
806 std::vector<VkPipelineColorBlendAttachmentState> colorBlendAttachmentStates(m_imageCount);
807
808 VkColorComponentFlags colorComponents =
809 VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
810
811 if (m_interleaveReadWriteComponents)
812 colorComponents = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_B_BIT;
813
814 for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
815 {
816 colorBlendAttachmentStates[imgNdx].blendEnable = false; // VkBool32 blendEnable;
817 colorBlendAttachmentStates[imgNdx].srcColorBlendFactor =
818 VK_BLEND_FACTOR_ONE; // VkBlendFactor srcColorBlendFactor;
819 colorBlendAttachmentStates[imgNdx].dstColorBlendFactor =
820 VK_BLEND_FACTOR_ZERO; // VkBlendFactor dstColorBlendFactor;
821 colorBlendAttachmentStates[imgNdx].colorBlendOp = VK_BLEND_OP_ADD; // VkBlendOp colorBlendOp;
822 colorBlendAttachmentStates[imgNdx].srcAlphaBlendFactor =
823 VK_BLEND_FACTOR_ONE; // VkBlendFactor srcAlphaBlendFactor;
824 colorBlendAttachmentStates[imgNdx].dstAlphaBlendFactor =
825 VK_BLEND_FACTOR_ZERO; // VkBlendFactor dstAlphaBlendFactor;
826 colorBlendAttachmentStates[imgNdx].alphaBlendOp = VK_BLEND_OP_ADD; // VkBlendOp alphaBlendOp;
827 colorBlendAttachmentStates[imgNdx].colorWriteMask =
828 colorComponents; // VkColorComponentFlags colorWriteMask;
829 }
830
831 const VkPipelineColorBlendStateCreateInfo colorBlendStateParams = {
832 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
833 DE_NULL, // const void* pNext;
834 0u, // VkPipelineColorBlendStateCreateFlags flags;
835 false, // VkBool32 logicOpEnable;
836 VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
837 (uint32_t)m_imageCount, // uint32_t attachmentCount;
838 &colorBlendAttachmentStates[0], // const VkPipelineColorBlendAttachmentState* pAttachments;
839 {0.0f, 0.0f, 0.0f, 0.0f} // float blendConstants[4];
840 };
841
842 std::vector<VkDynamicState> dynamicStates;
843 if (m_pipelineStateMode != PipelineStateMode::STATIC)
844 dynamicStates.push_back(VK_DYNAMIC_STATE_ATTACHMENT_FEEDBACK_LOOP_ENABLE_EXT);
845
846 const VkPipelineDynamicStateCreateInfo dynamicStateInfo = {
847 VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
848 nullptr,
849 0u,
850 de::sizeU32(dynamicStates),
851 de::dataOrNull(dynamicStates),
852 };
853
854 if (m_useMaintenance5)
855 m_graphicsPipeline.setPipelineCreateFlags2(translateCreateFlag(m_params.pipelineCreateFlags));
856
857 m_graphicsPipeline.setDynamicState(&dynamicStateInfo)
858 .setMonolithicPipelineLayout(m_fragmentStatePipelineLayout)
859 .setDefaultDepthStencilState()
860 .setDefaultRasterizationState()
861 .setDefaultMultisampleState()
862 .setupVertexInputState(&vertexInputStateParams)
863 .setupPreRasterizationShaderState(viewports, scissors, m_preRasterizationStatePipelineLayout, *m_renderPass,
864 0u, m_vertexShaderModule)
865 .setupFragmentShaderState(m_fragmentStatePipelineLayout, *m_renderPass, 0u, m_fragmentShaderModule)
866 .setupFragmentOutputState(*m_renderPass, 0u, &colorBlendStateParams)
867 .buildPipeline();
868 }
869
870 // Create vertex buffer
871 {
872 const VkDeviceSize vertexBufferSize = (VkDeviceSize)(m_vertices.size() * sizeof(Vertex4Tex4));
873 const VkBufferCreateInfo vertexBufferParams = {
874 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
875 DE_NULL, // const void* pNext;
876 0u, // VkBufferCreateFlags flags;
877 vertexBufferSize, // VkDeviceSize size;
878 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage;
879 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
880 1u, // uint32_t queueFamilyIndexCount;
881 &queueFamilyIndex // const uint32_t* pQueueFamilyIndices;
882 };
883
884 DE_ASSERT(vertexBufferSize > 0);
885
886 m_vertexBuffer = createBuffer(vk, vkDevice, &vertexBufferParams);
887 m_vertexBufferAlloc = allocateBuffer(vki, vk, physDevice, vkDevice, *m_vertexBuffer,
888 MemoryRequirement::HostVisible, memAlloc, m_allocationKind);
889 VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(),
890 m_vertexBufferAlloc->getOffset()));
891
892 // Load vertices into vertex buffer
893 deMemcpy(m_vertexBufferAlloc->getHostPtr(), &m_vertices[0], (size_t)vertexBufferSize);
894 flushAlloc(vk, vkDevice, *m_vertexBufferAlloc);
895 }
896
897 // Create command buffer
898 {
899 VkFormat clearFormat = m_useImageAsColorOrDSAttachment ? m_imageFormat : m_colorFormat;
900 const std::vector<VkClearValue> attachmentClearValues(m_imageCount, defaultClearValue(clearFormat));
901
902 std::vector<VkImageMemoryBarrier> preAttachmentBarriers(m_imageCount);
903
904 VkAccessFlags dstAccessMask = isDepthStencilFormat(m_imageFormat) ?
905 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT :
906 VK_ACCESS_SHADER_READ_BIT;
907 VkPipelineStageFlags pipelineStageFlags = isDepthStencilFormat(m_imageFormat) ?
908 VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT :
909 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
910
911 for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
912 {
913 preAttachmentBarriers[imgNdx].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; // VkStructureType sType;
914 preAttachmentBarriers[imgNdx].pNext = DE_NULL; // const void* pNext;
915 preAttachmentBarriers[imgNdx].srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; // VkAccessFlags srcAccessMask;
916 preAttachmentBarriers[imgNdx].dstAccessMask = dstAccessMask; // VkAccessFlags dstAccessMask;
917 preAttachmentBarriers[imgNdx].oldLayout = m_imageLayout; // VkImageLayout oldLayout;
918 preAttachmentBarriers[imgNdx].newLayout = m_imageLayout; // VkImageLayout newLayout;
919 preAttachmentBarriers[imgNdx].srcQueueFamilyIndex =
920 VK_QUEUE_FAMILY_IGNORED; // uint32_t srcQueueFamilyIndex;
921 preAttachmentBarriers[imgNdx].dstQueueFamilyIndex =
922 VK_QUEUE_FAMILY_IGNORED; // uint32_t dstQueueFamilyIndex;
923 preAttachmentBarriers[imgNdx].image = **m_images[imgNdx]; // VkImage image;
924 preAttachmentBarriers[imgNdx].subresourceRange =
925 m_subresourceRange; // VkImageSubresourceRange subresourceRange;
926 }
927
928 beginCommandBuffer(vk, *m_cmdBuffer, 0u);
929
930 vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, pipelineStageFlags, (VkDependencyFlags)0,
931 0u, DE_NULL, 0u, DE_NULL, (uint32_t)m_imageCount, &preAttachmentBarriers[0]);
932
933 if (!m_useImageAsColorOrDSAttachment)
934 {
935 // Pipeline barrier for the color attachment, which is a different image than the sampled one.
936 for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
937 {
938 preAttachmentBarriers[imgNdx].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; // VkStructureType sType;
939 preAttachmentBarriers[imgNdx].pNext = DE_NULL; // const void* pNext;
940 preAttachmentBarriers[imgNdx].srcAccessMask = (VkAccessFlagBits)0u; // VkAccessFlags srcAccessMask;
941 preAttachmentBarriers[imgNdx].dstAccessMask =
942 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; // VkAccessFlags dstAccessMask;
943 preAttachmentBarriers[imgNdx].oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; // VkImageLayout oldLayout;
944 preAttachmentBarriers[imgNdx].newLayout =
945 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; // VkImageLayout newLayout;
946 preAttachmentBarriers[imgNdx].srcQueueFamilyIndex =
947 VK_QUEUE_FAMILY_IGNORED; // uint32_t srcQueueFamilyIndex;
948 preAttachmentBarriers[imgNdx].dstQueueFamilyIndex =
949 VK_QUEUE_FAMILY_IGNORED; // uint32_t dstQueueFamilyIndex;
950 preAttachmentBarriers[imgNdx].image = **m_colorImages[imgNdx]; // VkImage image;
951 preAttachmentBarriers[imgNdx].subresourceRange.aspectMask =
952 getAspectFlags(m_colorFormat); // VkImageSubresourceRange subresourceRange;
953 preAttachmentBarriers[imgNdx].subresourceRange.baseMipLevel = 0u;
954 preAttachmentBarriers[imgNdx].subresourceRange.levelCount = 1u;
955 preAttachmentBarriers[imgNdx].subresourceRange.baseArrayLayer = 0u;
956 preAttachmentBarriers[imgNdx].subresourceRange.layerCount = 1u;
957 }
958
959 vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
960 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (VkDependencyFlags)0, 0u, DE_NULL, 0u,
961 DE_NULL, (uint32_t)m_imageCount, &preAttachmentBarriers[0]);
962
963 m_renderPass.begin(vk, *m_cmdBuffer, makeRect2D(0, 0, renderSize.x(), renderSize.y()),
964 (uint32_t)attachmentClearValues.size(), &attachmentClearValues[0]);
965 }
966 else
967 {
968 // Do not clear the color attachments as we are using the sampled texture as color attachment as well.
969 m_renderPass.begin(vk, *m_cmdBuffer, makeRect2D(0, 0, renderSize.x(), renderSize.y()), 0u, DE_NULL);
970 }
971
972 m_graphicsPipeline.bind(*m_cmdBuffer);
973
974 vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_fragmentStatePipelineLayout, 0, 1,
975 &m_descriptorSet.get(), 0, DE_NULL);
976
977 const VkDeviceSize vertexBufferOffset = 0;
978 vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
979
980 if (m_pipelineStateMode != PipelineStateMode::STATIC)
981 vk.cmdSetAttachmentFeedbackLoopEnableEXT(*m_cmdBuffer, testModeToAspectFlags(m_imageAspectTestMode));
982
983 vk.cmdDraw(*m_cmdBuffer, (uint32_t)m_vertices.size(), 1, 0, 0);
984
985 m_renderPass.end(vk, *m_cmdBuffer);
986 endCommandBuffer(vk, *m_cmdBuffer);
987 }
988 }
989
990 AttachmentFeedbackLoopLayoutDepthStencilImageSamplingInstance::
AttachmentFeedbackLoopLayoutDepthStencilImageSamplingInstance(Context & context,ImageSamplingInstanceParams params,bool useImageAsColorOrDSAttachment_,bool useDifferentAreasSampleWrite_,bool interleaveReadWriteComponents_,ImageAspectTestMode imageAspectTestMode,PipelineStateMode pipelineStateMode,bool useMaintenance5_)991 AttachmentFeedbackLoopLayoutDepthStencilImageSamplingInstance(
992 Context &context, ImageSamplingInstanceParams params, bool useImageAsColorOrDSAttachment_,
993 bool useDifferentAreasSampleWrite_, bool interleaveReadWriteComponents_,
994 ImageAspectTestMode imageAspectTestMode, PipelineStateMode pipelineStateMode, bool useMaintenance5_)
995 : AttachmentFeedbackLoopLayoutImageSamplingInstance(context, params, useImageAsColorOrDSAttachment_,
996 useDifferentAreasSampleWrite_, interleaveReadWriteComponents_,
997 imageAspectTestMode, pipelineStateMode, useMaintenance5_)
998 , m_separateStencilUsage(params.separateStencilUsage)
999 {
1000 }
1001
1002 AttachmentFeedbackLoopLayoutDepthStencilImageSamplingInstance::
~AttachmentFeedbackLoopLayoutDepthStencilImageSamplingInstance(void)1003 ~AttachmentFeedbackLoopLayoutDepthStencilImageSamplingInstance(void)
1004 {
1005 }
1006
setup(void)1007 void AttachmentFeedbackLoopLayoutDepthStencilImageSamplingInstance::setup(void)
1008 {
1009 const InstanceInterface &vki = m_context.getInstanceInterface();
1010 const DeviceInterface &vk = m_context.getDeviceInterface();
1011 const VkPhysicalDevice physDevice = m_context.getPhysicalDevice();
1012 const VkDevice vkDevice = m_context.getDevice();
1013 const VkQueue queue = m_context.getUniversalQueue();
1014 const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1015 SimpleAllocator memAlloc(
1016 vk, vkDevice,
1017 getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
1018 tcu::UVec2 renderSize = tcu::UVec2({(unsigned)m_imageSize.x(), (unsigned)m_imageSize.y()});
1019
1020 DE_ASSERT(m_useImageAsColorOrDSAttachment && isDepthStencilFormat(m_imageFormat));
1021 DE_ASSERT(m_samplerParams.pNext == DE_NULL);
1022
1023 // Create texture images, views
1024 {
1025 VkImageCreateFlags imageFlags = 0u;
1026
1027 if (m_imageViewType == VK_IMAGE_VIEW_TYPE_CUBE || m_imageViewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
1028 imageFlags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
1029
1030 // Initialize texture data
1031 if (isCompressedFormat(m_imageFormat))
1032 m_texture =
1033 createTestTexture(mapVkCompressedFormat(m_imageFormat), m_imageViewType, m_imageSize, m_layerCount);
1034 else
1035 m_texture = createTestTexture(mapVkFormat(m_imageFormat), m_imageViewType, m_imageSize, m_layerCount);
1036
1037 VkImageUsageFlags imageUsageFlags = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
1038 VK_IMAGE_USAGE_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT |
1039 VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
1040 VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
1041
1042 const VkImageCreateInfo imageParams = {
1043 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
1044 DE_NULL, // const void* pNext;
1045 imageFlags, // VkImageCreateFlags flags;
1046 getCompatibleImageType(m_imageViewType), // VkImageType imageType;
1047 m_imageFormat, // VkFormat format;
1048 { // VkExtent3D extent;
1049 (uint32_t)m_imageSize.x(), (uint32_t)m_imageSize.y(), (uint32_t)m_imageSize.z()},
1050 (uint32_t)m_texture->getNumLevels(), // uint32_t mipLevels;
1051 (uint32_t)m_layerCount, // uint32_t arrayLayers;
1052 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
1053 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
1054 imageUsageFlags, // VkImageUsageFlags usage;
1055 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1056 1u, // uint32_t queueFamilyIndexCount;
1057 &queueFamilyIndex, // const uint32_t* pQueueFamilyIndices;
1058 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
1059 };
1060
1061 checkImageSupport(vki, physDevice, imageParams);
1062
1063 m_images.resize(m_imageCount);
1064 m_imageAllocs.resize(m_imageCount);
1065
1066 // Create command pool
1067 m_cmdPool = createCommandPool(
1068 vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT | VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
1069 queueFamilyIndex);
1070 m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1071
1072 int numImageViews = m_interleaveReadWriteComponents ? m_imageCount + 1 : m_imageCount;
1073 m_imageViews.resize(numImageViews);
1074
1075 for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
1076 {
1077 m_images[imgNdx] = SharedImagePtr(new UniqueImage(createImage(vk, vkDevice, &imageParams)));
1078 m_imageAllocs[imgNdx] =
1079 SharedAllocPtr(new UniqueAlloc(allocateImage(vki, vk, physDevice, vkDevice, **m_images[imgNdx],
1080 MemoryRequirement::Any, memAlloc, m_allocationKind)));
1081 VK_CHECK(vk.bindImageMemory(vkDevice, **m_images[imgNdx], (*m_imageAllocs[imgNdx])->getMemory(),
1082 (*m_imageAllocs[imgNdx])->getOffset()));
1083
1084 // Upload texture data
1085 uploadTestTexture(vk, vkDevice, queue, queueFamilyIndex, memAlloc, *m_texture, **m_images[imgNdx],
1086 m_imageLayout);
1087 }
1088
1089 for (int imgNdx = 0; imgNdx < numImageViews; ++imgNdx)
1090 {
1091 VkImage image = (m_interleaveReadWriteComponents && imgNdx == m_imageCount) ? **m_images[imgNdx - 1] :
1092 **m_images[imgNdx];
1093
1094 // Create image view and sampler
1095 VkImageViewCreateInfo imageViewParams = {
1096 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
1097 DE_NULL, // const void* pNext;
1098 0u, // VkImageViewCreateFlags flags;
1099 image, // VkImage image;
1100 m_imageViewType, // VkImageViewType viewType;
1101 m_imageFormat, // VkFormat format;
1102 m_componentMapping, // VkComponentMapping components;
1103 m_subresourceRange, // VkImageSubresourceRange subresourceRange;
1104 };
1105
1106 if (m_interleaveReadWriteComponents && imgNdx == m_imageCount)
1107 {
1108 imageViewParams.subresourceRange.aspectMask = getImageAspectFlags(mapVkFormat(m_imageFormat));
1109 }
1110
1111 m_imageViews[imgNdx] =
1112 SharedImageViewPtr(new UniqueImageView(createImageView(vk, vkDevice, &imageViewParams)));
1113 }
1114
1115 m_sampler = createSampler(vk, vkDevice, &m_samplerParams);
1116 }
1117
1118 // Create descriptor set for image and sampler
1119 {
1120 DescriptorPoolBuilder descriptorPoolBuilder;
1121 if (m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
1122 descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_SAMPLER, 1u);
1123 descriptorPoolBuilder.addType(m_samplingType, m_imageCount);
1124 m_descriptorPool = descriptorPoolBuilder.build(
1125 vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
1126 m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ? m_imageCount + 1u : m_imageCount);
1127
1128 DescriptorSetLayoutBuilder setLayoutBuilder;
1129 if (m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
1130 setLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT);
1131 setLayoutBuilder.addArrayBinding(m_samplingType, m_imageCount, VK_SHADER_STAGE_FRAGMENT_BIT);
1132 m_descriptorSetLayout = setLayoutBuilder.build(vk, vkDevice);
1133
1134 const VkDescriptorSetAllocateInfo descriptorSetAllocateInfo = {
1135 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // VkStructureType sType;
1136 DE_NULL, // const void* pNext;
1137 *m_descriptorPool, // VkDescriptorPool descriptorPool;
1138 1u, // uint32_t setLayoutCount;
1139 &m_descriptorSetLayout.get() // const VkDescriptorSetLayout* pSetLayouts;
1140 };
1141
1142 m_descriptorSet = allocateDescriptorSet(vk, vkDevice, &descriptorSetAllocateInfo);
1143
1144 const VkSampler sampler = m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ? DE_NULL : *m_sampler;
1145 std::vector<VkDescriptorImageInfo> descriptorImageInfo(m_imageCount);
1146 for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
1147 {
1148 descriptorImageInfo[imgNdx].sampler = sampler; // VkSampler sampler;
1149 descriptorImageInfo[imgNdx].imageView = **m_imageViews[imgNdx]; // VkImageView imageView;
1150 descriptorImageInfo[imgNdx].imageLayout = m_imageLayout; // VkImageLayout imageLayout;
1151 }
1152
1153 DescriptorSetUpdateBuilder setUpdateBuilder;
1154 if (m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
1155 {
1156 const VkDescriptorImageInfo descriptorSamplerInfo = {
1157 *m_sampler, // VkSampler sampler;
1158 DE_NULL, // VkImageView imageView;
1159 m_imageLayout, // VkImageLayout imageLayout;
1160 };
1161 setUpdateBuilder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0),
1162 VK_DESCRIPTOR_TYPE_SAMPLER, &descriptorSamplerInfo);
1163 }
1164
1165 const uint32_t binding = m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ? 1u : 0u;
1166 setUpdateBuilder.writeArray(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(binding),
1167 m_samplingType, m_imageCount, descriptorImageInfo.data());
1168 setUpdateBuilder.update(vk, vkDevice);
1169 }
1170
1171 // Create depth-stencil images and views, no color attachment
1172 {
1173 m_dsImages.resize(m_imageCount);
1174 m_dsImageAllocs.resize(m_imageCount);
1175 m_dsAttachmentViews.resize(m_imageCount);
1176
1177 for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
1178 {
1179 m_dsImages[imgNdx] = m_images[imgNdx];
1180 m_dsImageAllocs[imgNdx] = m_imageAllocs[imgNdx];
1181 m_dsAttachmentViews[imgNdx] =
1182 m_interleaveReadWriteComponents ? m_imageViews[imgNdx + 1] : m_imageViews[imgNdx];
1183 }
1184 }
1185
1186 // Create render pass
1187 {
1188 std::vector<VkAttachmentDescription> attachmentDescriptions(m_imageCount);
1189 std::vector<VkAttachmentReference> attachmentReferences(m_imageCount);
1190
1191 for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
1192 {
1193 attachmentDescriptions[imgNdx].flags = 0u; // VkAttachmentDescriptionFlags flags;
1194 attachmentDescriptions[imgNdx].format =
1195 m_useImageAsColorOrDSAttachment ? m_imageFormat : m_colorFormat; // VkFormat format;
1196 attachmentDescriptions[imgNdx].samples = VK_SAMPLE_COUNT_1_BIT; // VkSampleCountFlagBits samples;
1197 attachmentDescriptions[imgNdx].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; // VkAttachmentLoadOp loadOp;
1198 attachmentDescriptions[imgNdx].storeOp = VK_ATTACHMENT_STORE_OP_STORE; // VkAttachmentStoreOp storeOp;
1199 attachmentDescriptions[imgNdx].stencilLoadOp =
1200 VK_ATTACHMENT_LOAD_OP_LOAD; // VkAttachmentLoadOp stencilLoadOp;
1201 attachmentDescriptions[imgNdx].stencilStoreOp =
1202 VK_ATTACHMENT_STORE_OP_STORE; // VkAttachmentStoreOp stencilStoreOp;
1203 attachmentDescriptions[imgNdx].initialLayout = m_imageLayout; // VkImageLayout initialLayout;
1204 attachmentDescriptions[imgNdx].finalLayout = m_imageLayout; // VkImageLayout finalLayout;
1205
1206 attachmentReferences[imgNdx].attachment = (uint32_t)imgNdx; // uint32_t attachment;
1207 attachmentReferences[imgNdx].layout = m_imageLayout; // VkImageLayout layout;
1208 }
1209
1210 const VkSubpassDescription subpassDescription = {
1211 0u, // VkSubpassDescriptionFlags flags;
1212 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
1213 0u, // uint32_t inputAttachmentCount;
1214 DE_NULL, // const VkAttachmentReference* pInputAttachments;
1215 0u, // uint32_t colorAttachmentCount;
1216 DE_NULL, // const VkAttachmentReference* pColorAttachments;
1217 DE_NULL, // const VkAttachmentReference* pResolveAttachments;
1218 &attachmentReferences[0], // const VkAttachmentReference* pDepthStencilAttachment;
1219 0u, // uint32_t preserveAttachmentCount;
1220 DE_NULL // const VkAttachmentReference* pPreserveAttachments;
1221 };
1222
1223 std::vector<VkSubpassDependency> subpassDependencies;
1224
1225 if (m_useImageAsColorOrDSAttachment)
1226 {
1227 const auto srcStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
1228 const auto srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
1229 const auto dstStageMask =
1230 (VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT);
1231 const auto dstAccessMask =
1232 (VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT);
1233
1234 const VkSubpassDependency spdVal = {
1235 0u, // uint32_t srcSubpass;
1236 0u, // uint32_t dstSubpass;
1237 srcStageMask, // VkPipelineStageFlags srcStageMask;
1238 dstStageMask, // VkPipelineStageFlags dstStageMask;
1239 srcAccessMask, // VkAccessFlags srcAccessMask;
1240 dstAccessMask, // VkAccessFlags dstAccessMask;
1241 VK_DEPENDENCY_FEEDBACK_LOOP_BIT_EXT | VK_DEPENDENCY_BY_REGION_BIT, // VkDependencyFlags dependencyFlags;
1242 };
1243
1244 subpassDependencies.push_back(spdVal);
1245 }
1246
1247 const VkRenderPassCreateInfo renderPassParams = {
1248 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
1249 DE_NULL, // const void* pNext;
1250 0u, // VkRenderPassCreateFlags flags;
1251 (uint32_t)attachmentDescriptions.size(), // uint32_t attachmentCount;
1252 &attachmentDescriptions[0], // const VkAttachmentDescription* pAttachments;
1253 1u, // uint32_t subpassCount;
1254 &subpassDescription, // const VkSubpassDescription* pSubpasses;
1255 static_cast<uint32_t>(subpassDependencies.size()), // uint32_t dependencyCount;
1256 de::dataOrNull(subpassDependencies), // const VkSubpassDependency* pDependencies;
1257 };
1258
1259 m_renderPass = RenderPassWrapper(m_pipelineConstructionType, vk, vkDevice, &renderPassParams);
1260 }
1261
1262 // Create framebuffer
1263 {
1264 std::vector<VkImage> images(m_imageCount);
1265 std::vector<VkImageView> pAttachments(m_imageCount);
1266 for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
1267 {
1268 images[imgNdx] = m_dsImages[imgNdx]->get();
1269 pAttachments[imgNdx] = m_dsAttachmentViews[imgNdx]->get();
1270 }
1271
1272 const VkFramebufferCreateInfo framebufferParams = {
1273 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
1274 DE_NULL, // const void* pNext;
1275 0u, // VkFramebufferCreateFlags flags;
1276 *m_renderPass, // VkRenderPass renderPass;
1277 (uint32_t)m_imageCount, // uint32_t attachmentCount;
1278 &pAttachments[0], // const VkImageView* pAttachments;
1279 (uint32_t)renderSize.x(), // uint32_t width;
1280 (uint32_t)renderSize.y(), // uint32_t height;
1281 1u // uint32_t layers;
1282 };
1283
1284 m_renderPass.createFramebuffer(vk, vkDevice, &framebufferParams, images);
1285 }
1286
1287 // Create pipeline layouts
1288 {
1289 const VkPipelineLayoutCreateInfo pipelineLayoutParams = {
1290 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
1291 DE_NULL, // const void* pNext;
1292 0u, // VkPipelineLayoutCreateFlags flags;
1293 0u, // uint32_t setLayoutCount;
1294 DE_NULL, // const VkDescriptorSetLayout* pSetLayouts;
1295 0u, // uint32_t pushConstantRangeCount;
1296 DE_NULL // const VkPushConstantRange* pPushConstantRanges;
1297 };
1298
1299 m_preRasterizationStatePipelineLayout =
1300 PipelineLayoutWrapper(m_pipelineConstructionType, vk, vkDevice, &pipelineLayoutParams);
1301 }
1302 {
1303 const VkPipelineLayoutCreateInfo pipelineLayoutParams = {
1304 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
1305 DE_NULL, // const void* pNext;
1306 VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT, // VkPipelineLayoutCreateFlags flags;
1307 0u, // uint32_t setLayoutCount;
1308 DE_NULL, // const VkDescriptorSetLayout* pSetLayouts;
1309 0u, // uint32_t pushConstantRangeCount;
1310 DE_NULL // const VkPushConstantRange* pPushConstantRanges;
1311 };
1312
1313 m_preRasterizationStatePipelineLayout =
1314 PipelineLayoutWrapper(m_pipelineConstructionType, vk, vkDevice, &pipelineLayoutParams);
1315 }
1316 {
1317 const VkPipelineLayoutCreateInfo pipelineLayoutParams = {
1318 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
1319 DE_NULL, // const void* pNext;
1320 VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT, // VkPipelineLayoutCreateFlags flags;
1321 1u, // uint32_t setLayoutCount;
1322 &m_descriptorSetLayout.get(), // const VkDescriptorSetLayout* pSetLayouts;
1323 0u, // uint32_t pushConstantRangeCount;
1324 DE_NULL // const VkPushConstantRange* pPushConstantRanges;
1325 };
1326
1327 m_fragmentStatePipelineLayout =
1328 PipelineLayoutWrapper(m_pipelineConstructionType, vk, vkDevice, &pipelineLayoutParams);
1329 }
1330
1331 m_vertexShaderModule = ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("tex_vert"), 0);
1332 m_fragmentShaderModule = ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("tex_frag"), 0);
1333
1334 // Create pipeline
1335 {
1336 const VkVertexInputBindingDescription vertexInputBindingDescription = {
1337 0u, // uint32_t binding;
1338 sizeof(Vertex4Tex4), // uint32_t strideInBytes;
1339 VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputStepRate inputRate;
1340 };
1341
1342 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] = {
1343 {
1344 0u, // uint32_t location;
1345 0u, // uint32_t binding;
1346 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
1347 0u // uint32_t offset;
1348 },
1349 {
1350 1u, // uint32_t location;
1351 0u, // uint32_t binding;
1352 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
1353 offsetof(Vertex4Tex4, texCoord), // uint32_t offset;
1354 }};
1355
1356 const VkPipelineVertexInputStateCreateInfo vertexInputStateParams = {
1357 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
1358 DE_NULL, // const void* pNext;
1359 0u, // VkPipelineVertexInputStateCreateFlags flags;
1360 1u, // uint32_t vertexBindingDescriptionCount;
1361 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
1362 2u, // uint32_t vertexAttributeDescriptionCount;
1363 vertexInputAttributeDescriptions // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
1364 };
1365
1366 const std::vector<VkViewport> viewports(1, makeViewport(renderSize));
1367 const std::vector<VkRect2D> scissors(1, makeRect2D(renderSize));
1368
1369 std::vector<VkPipelineColorBlendAttachmentState> colorBlendAttachmentStates(m_imageCount);
1370
1371 for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
1372 {
1373 colorBlendAttachmentStates[imgNdx].blendEnable = false; // VkBool32 blendEnable;
1374 colorBlendAttachmentStates[imgNdx].srcColorBlendFactor =
1375 VK_BLEND_FACTOR_ONE; // VkBlendFactor srcColorBlendFactor;
1376 colorBlendAttachmentStates[imgNdx].dstColorBlendFactor =
1377 VK_BLEND_FACTOR_ZERO; // VkBlendFactor dstColorBlendFactor;
1378 colorBlendAttachmentStates[imgNdx].colorBlendOp = VK_BLEND_OP_ADD; // VkBlendOp colorBlendOp;
1379 colorBlendAttachmentStates[imgNdx].srcAlphaBlendFactor =
1380 VK_BLEND_FACTOR_ONE; // VkBlendFactor srcAlphaBlendFactor;
1381 colorBlendAttachmentStates[imgNdx].dstAlphaBlendFactor =
1382 VK_BLEND_FACTOR_ZERO; // VkBlendFactor dstAlphaBlendFactor;
1383 colorBlendAttachmentStates[imgNdx].alphaBlendOp = VK_BLEND_OP_ADD; // VkBlendOp alphaBlendOp;
1384 colorBlendAttachmentStates[imgNdx].colorWriteMask = 0u; // VkColorComponentFlags colorWriteMask;
1385 }
1386
1387 const VkPipelineColorBlendStateCreateInfo colorBlendStateParams = {
1388 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
1389 DE_NULL, // const void* pNext;
1390 0u, // VkPipelineColorBlendStateCreateFlags flags;
1391 false, // VkBool32 logicOpEnable;
1392 VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
1393 0u, // uint32_t attachmentCount;
1394 DE_NULL, // const VkPipelineColorBlendAttachmentState* pAttachments;
1395 {0.0f, 0.0f, 0.0f, 0.0f} // float blendConstants[4];
1396 };
1397
1398 VkBool32 depthTestEnable =
1399 ((m_subresourceRange.aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) && !m_interleaveReadWriteComponents) ||
1400 ((m_subresourceRange.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) && m_interleaveReadWriteComponents);
1401
1402 VkBool32 stencilTestEnable =
1403 ((m_subresourceRange.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) && !m_interleaveReadWriteComponents) ||
1404 ((m_subresourceRange.aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) && m_interleaveReadWriteComponents);
1405
1406 const auto stencilFrontOpState =
1407 makeStencilOpState(vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_REPLACE, vk::VK_STENCIL_OP_KEEP,
1408 vk::VK_COMPARE_OP_NEVER, 0xFFu, 0xFFu, 0u);
1409 const auto stencilBackOpState =
1410 makeStencilOpState(vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_REPLACE, vk::VK_STENCIL_OP_KEEP,
1411 vk::VK_COMPARE_OP_ALWAYS, 0xFFu, 0xFFu, 0u);
1412
1413 const VkPipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo = {
1414 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType
1415 DE_NULL, // const void* pNext
1416 0u, // VkPipelineDepthStencilStateCreateFlags flags
1417 depthTestEnable, // VkBool32 depthTestEnable
1418 depthTestEnable, // VkBool32 depthWriteEnable
1419 VK_COMPARE_OP_ALWAYS, // VkCompareOp depthCompareOp
1420 false, // VkBool32 depthBoundsTestEnable
1421 stencilTestEnable, // VkBool32 stencilTestEnable
1422 stencilFrontOpState, // VkStencilOpState front
1423 stencilBackOpState, // VkStencilOpState back
1424 0.0f, // float minDepthBounds
1425 1.0f, // float maxDepthBounds;
1426 };
1427
1428 std::vector<VkDynamicState> dynamicStates;
1429 if (m_pipelineStateMode != PipelineStateMode::STATIC)
1430 dynamicStates.push_back(VK_DYNAMIC_STATE_ATTACHMENT_FEEDBACK_LOOP_ENABLE_EXT);
1431
1432 const VkPipelineDynamicStateCreateInfo dynamicStateInfo = {
1433 VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
1434 nullptr,
1435 0u,
1436 de::sizeU32(dynamicStates),
1437 de::dataOrNull(dynamicStates),
1438 };
1439
1440 if (m_useMaintenance5)
1441 m_graphicsPipeline.setPipelineCreateFlags2(translateCreateFlag(m_params.pipelineCreateFlags));
1442
1443 m_graphicsPipeline.setDynamicState(&dynamicStateInfo)
1444 .setMonolithicPipelineLayout(m_fragmentStatePipelineLayout)
1445 .setDefaultDepthStencilState()
1446 .setDefaultRasterizationState()
1447 .setDefaultMultisampleState()
1448 .setupVertexInputState(&vertexInputStateParams)
1449 .setupPreRasterizationShaderState(viewports, scissors, m_preRasterizationStatePipelineLayout, *m_renderPass,
1450 0u, m_vertexShaderModule)
1451 .setupFragmentShaderState(m_fragmentStatePipelineLayout, *m_renderPass, 0u, m_fragmentShaderModule,
1452 &depthStencilStateCreateInfo)
1453 .setupFragmentOutputState(*m_renderPass, 0u, &colorBlendStateParams)
1454 .buildPipeline();
1455 }
1456
1457 // Create vertex buffer
1458 {
1459 const VkDeviceSize vertexBufferSize = (VkDeviceSize)(m_vertices.size() * sizeof(Vertex4Tex4));
1460 const VkBufferCreateInfo vertexBufferParams = {
1461 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
1462 DE_NULL, // const void* pNext;
1463 0u, // VkBufferCreateFlags flags;
1464 vertexBufferSize, // VkDeviceSize size;
1465 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage;
1466 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1467 1u, // uint32_t queueFamilyIndexCount;
1468 &queueFamilyIndex // const uint32_t* pQueueFamilyIndices;
1469 };
1470
1471 DE_ASSERT(vertexBufferSize > 0);
1472
1473 m_vertexBuffer = createBuffer(vk, vkDevice, &vertexBufferParams);
1474 m_vertexBufferAlloc = allocateBuffer(vki, vk, physDevice, vkDevice, *m_vertexBuffer,
1475 MemoryRequirement::HostVisible, memAlloc, m_allocationKind);
1476 VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(),
1477 m_vertexBufferAlloc->getOffset()));
1478
1479 // Load vertices into vertex buffer
1480 deMemcpy(m_vertexBufferAlloc->getHostPtr(), &m_vertices[0], (size_t)vertexBufferSize);
1481 flushAlloc(vk, vkDevice, *m_vertexBufferAlloc);
1482 }
1483
1484 // Create command buffer
1485 {
1486 std::vector<VkImageMemoryBarrier> preAttachmentBarriers(m_imageCount);
1487
1488 for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
1489 {
1490 preAttachmentBarriers[imgNdx].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; // VkStructureType sType;
1491 preAttachmentBarriers[imgNdx].pNext = DE_NULL; // const void* pNext;
1492 preAttachmentBarriers[imgNdx].srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; // VkAccessFlags srcAccessMask;
1493 preAttachmentBarriers[imgNdx].dstAccessMask =
1494 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
1495 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; // VkAccessFlags dstAccessMask;
1496 preAttachmentBarriers[imgNdx].oldLayout = m_imageLayout; // VkImageLayout oldLayout;
1497 preAttachmentBarriers[imgNdx].newLayout = m_imageLayout; // VkImageLayout newLayout;
1498 preAttachmentBarriers[imgNdx].srcQueueFamilyIndex =
1499 VK_QUEUE_FAMILY_IGNORED; // uint32_t srcQueueFamilyIndex;
1500 preAttachmentBarriers[imgNdx].dstQueueFamilyIndex =
1501 VK_QUEUE_FAMILY_IGNORED; // uint32_t dstQueueFamilyIndex;
1502 preAttachmentBarriers[imgNdx].image = **m_dsImages[imgNdx]; // VkImage image;
1503 preAttachmentBarriers[imgNdx].subresourceRange.aspectMask =
1504 getAspectFlags(m_imageFormat); // VkImageSubresourceRange subresourceRange;
1505 preAttachmentBarriers[imgNdx].subresourceRange.baseMipLevel = 0u;
1506 preAttachmentBarriers[imgNdx].subresourceRange.levelCount = 1u;
1507 preAttachmentBarriers[imgNdx].subresourceRange.baseArrayLayer = 0u;
1508 preAttachmentBarriers[imgNdx].subresourceRange.layerCount = 1u;
1509 }
1510
1511 beginCommandBuffer(vk, *m_cmdBuffer, 0u);
1512
1513 vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT,
1514 (VkDependencyFlags)0, 0u, DE_NULL, 0u, DE_NULL, (uint32_t)m_imageCount,
1515 &preAttachmentBarriers[0]);
1516
1517 // Do not clear the color attachments as we are using the texture as color attachment.
1518 m_renderPass.begin(vk, *m_cmdBuffer, makeRect2D(0, 0, renderSize.x(), renderSize.y()), 0u, DE_NULL);
1519
1520 m_graphicsPipeline.bind(*m_cmdBuffer);
1521
1522 vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_fragmentStatePipelineLayout, 0, 1,
1523 &m_descriptorSet.get(), 0, DE_NULL);
1524
1525 const VkDeviceSize vertexBufferOffset = 0;
1526 vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
1527
1528 if (m_pipelineStateMode != PipelineStateMode::STATIC)
1529 vk.cmdSetAttachmentFeedbackLoopEnableEXT(*m_cmdBuffer, testModeToAspectFlags(m_imageAspectTestMode));
1530
1531 vk.cmdDraw(*m_cmdBuffer, (uint32_t)m_vertices.size(), 1, 0, 0);
1532
1533 m_renderPass.end(vk, *m_cmdBuffer);
1534 endCommandBuffer(vk, *m_cmdBuffer);
1535 }
1536 }
1537
verifyImage(void)1538 tcu::TestStatus AttachmentFeedbackLoopLayoutDepthStencilImageSamplingInstance::verifyImage(void)
1539 {
1540 const tcu::TextureFormat tcuFormat = getSizeCompatibleTcuTextureFormat(m_imageFormat);
1541 const bool isDepth =
1542 (!m_interleaveReadWriteComponents && (m_subresourceRange.aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT)) ||
1543 (m_interleaveReadWriteComponents && (m_subresourceRange.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT));
1544 const bool isStencil =
1545 (!m_interleaveReadWriteComponents && (m_subresourceRange.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT)) ||
1546 (m_interleaveReadWriteComponents && (m_subresourceRange.aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT));
1547 // ImageSamplingInstance::verifyImage() doesn't support stencil sampling.
1548 if (!m_useImageAsColorOrDSAttachment && !isStencil)
1549 return ImageSamplingInstance::verifyImage();
1550
1551 const tcu::Vec4 fThreshold(0.005f);
1552 const tcu::UVec4 uThreshold(
1553 0u); // Due to unsigned normalized fixed-point integers conversion to floats and viceversa.
1554 tcu::UVec2 renderSize = tcu::UVec2({(unsigned)m_imageSize.x(), (unsigned)m_imageSize.y()});
1555
1556 de::MovePtr<tcu::TextureLevel> referenceTextureLevel = de::MovePtr<tcu::TextureLevel>(
1557 new tcu::TextureLevel(tcuFormat, m_imageSize.x(), m_imageSize.y(), m_imageSize.z()));
1558
1559 for (int z = 0; z < m_imageSize.z(); z++)
1560 for (int y = 0; y < m_imageSize.y(); y++)
1561 for (int x = 0; x < m_imageSize.x(); x++)
1562 {
1563 if (isDepth)
1564 {
1565 float depth = 0.0f;
1566 if (m_interleaveReadWriteComponents)
1567 {
1568 int stencil = 1 + m_texture->getLevel(0, 0).getPixStencil(x, y, z);
1569 depth = static_cast<float>(stencil) / 255.0f;
1570 }
1571 else
1572 {
1573 if (m_useDifferentAreasSampleWrite && x < m_imageSize.x() / 2)
1574 depth = m_texture->getLevel(0, 0).getPixDepth(x + (m_imageSize.x() / 2), y, z) + 0.1f;
1575 else
1576 depth = m_texture->getLevel(0, 0).getPixDepth(x, y, z);
1577
1578 if (!m_useDifferentAreasSampleWrite)
1579 depth += 0.1f;
1580 }
1581
1582 depth = deFloatClamp(depth, 0.0f, 1.0f);
1583 referenceTextureLevel->getAccess().setPixDepth(depth, x, y, z);
1584 }
1585 if (isStencil)
1586 {
1587 int stencil = 0;
1588 if (m_interleaveReadWriteComponents)
1589 {
1590 float depth = m_texture->getLevel(0, 0).getPixDepth(x, y, z) + 0.1f;
1591 stencil = static_cast<int>(depth * 255.0f);
1592 }
1593 else
1594 {
1595 if (m_useDifferentAreasSampleWrite && x < m_imageSize.x() / 2)
1596 stencil = 1 + m_texture->getLevel(0, 0).getPixStencil(x + (m_imageSize.x() / 2), y, z);
1597 else
1598 stencil = m_texture->getLevel(0, 0).getPixStencil(x, y, z);
1599
1600 if (!m_useDifferentAreasSampleWrite)
1601 stencil += 1;
1602
1603 stencil = deClamp32(stencil, 0, 255);
1604 }
1605
1606 referenceTextureLevel->getAccess().setPixStencil(stencil, x, y, z);
1607 }
1608 }
1609
1610 for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
1611 {
1612 if (isDepth)
1613 {
1614 // Read back result image
1615 de::MovePtr<tcu::TextureLevel> resultTexture(readDepthAttachment(
1616 m_context.getDeviceInterface(), m_context.getDevice(), m_context.getUniversalQueue(),
1617 m_context.getUniversalQueueFamilyIndex(), m_context.getDefaultAllocator(), **m_dsImages[imgNdx],
1618 m_imageFormat, renderSize, VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT));
1619
1620 const tcu::ConstPixelBufferAccess result = resultTexture->getAccess();
1621 const tcu::Sampler::DepthStencilMode mode = tcu::Sampler::MODE_DEPTH;
1622 const tcu::ConstPixelBufferAccess depthResult = tcu::getEffectiveDepthStencilAccess(result, mode);
1623 const tcu::ConstPixelBufferAccess expectedResult =
1624 tcu::getEffectiveDepthStencilAccess(referenceTextureLevel->getAccess(), mode);
1625 bool isIntegerFormat = isUintFormat(mapTextureFormat(depthResult.getFormat())) ||
1626 isIntFormat(mapTextureFormat(depthResult.getFormat()));
1627
1628 if (!isIntegerFormat)
1629 {
1630 if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison",
1631 expectedResult, depthResult, fThreshold, tcu::COMPARE_LOG_RESULT))
1632 return tcu::TestStatus::fail("Failed depth");
1633 }
1634 else
1635 {
1636 if (!tcu::intThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison",
1637 expectedResult, depthResult, uThreshold, tcu::COMPARE_LOG_RESULT))
1638 return tcu::TestStatus::fail("Failed depth");
1639 }
1640 }
1641
1642 if (isStencil)
1643 {
1644 // Read back result image
1645 de::MovePtr<tcu::TextureLevel> resultTexture(readStencilAttachment(
1646 m_context.getDeviceInterface(), m_context.getDevice(), m_context.getUniversalQueue(),
1647 m_context.getUniversalQueueFamilyIndex(), m_context.getDefaultAllocator(), **m_dsImages[imgNdx],
1648 m_imageFormat, renderSize, VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT));
1649
1650 const tcu::ConstPixelBufferAccess result = resultTexture->getAccess();
1651 const tcu::Sampler::DepthStencilMode mode = tcu::Sampler::MODE_STENCIL;
1652 const tcu::ConstPixelBufferAccess stencilResult = tcu::getEffectiveDepthStencilAccess(result, mode);
1653 const tcu::ConstPixelBufferAccess expectedResult =
1654 tcu::getEffectiveDepthStencilAccess(referenceTextureLevel->getAccess(), mode);
1655 bool isIntegerFormat = isUintFormat(mapTextureFormat(stencilResult.getFormat())) ||
1656 isIntFormat(mapTextureFormat(stencilResult.getFormat()));
1657
1658 if (!isIntegerFormat)
1659 {
1660 if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison",
1661 expectedResult, stencilResult, fThreshold, tcu::COMPARE_LOG_RESULT))
1662 return tcu::TestStatus::fail("Failed stencil");
1663 }
1664 else
1665 {
1666 if (!tcu::intThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison",
1667 expectedResult, stencilResult, uThreshold, tcu::COMPARE_LOG_RESULT))
1668 return tcu::TestStatus::fail("Failed stencil");
1669 }
1670 }
1671 }
1672
1673 return tcu::TestStatus::pass("Pass");
1674 }
1675
iterate(void)1676 tcu::TestStatus AttachmentFeedbackLoopLayoutDepthStencilImageSamplingInstance::iterate(void)
1677 {
1678 const DeviceInterface &vk = m_context.getDeviceInterface();
1679 const VkDevice vkDevice = m_context.getDevice();
1680 const VkQueue queue = m_context.getUniversalQueue();
1681
1682 setup();
1683 submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
1684
1685 return verifyImage();
1686 }
1687
verifyImage(void)1688 tcu::TestStatus AttachmentFeedbackLoopLayoutImageSamplingInstance::verifyImage(void)
1689 {
1690 if (!m_useImageAsColorOrDSAttachment)
1691 return ImageSamplingInstance::verifyImage();
1692
1693 const tcu::Vec4 fThreshold(0.01f);
1694 const tcu::UVec4 uThreshold(1u);
1695 tcu::UVec2 renderSize = tcu::UVec2({(unsigned)m_imageSize.x(), (unsigned)m_imageSize.y()});
1696
1697 const tcu::TextureFormat tcuFormat = getSizeCompatibleTcuTextureFormat(m_imageFormat);
1698 de::MovePtr<tcu::TextureLevel> referenceTextureLevel = de::MovePtr<tcu::TextureLevel>(
1699 new tcu::TextureLevel(tcuFormat, m_imageSize.x(), m_imageSize.y(), m_imageSize.z()));
1700
1701 for (int z = 0; z < m_imageSize.z(); z++)
1702 for (int y = 0; y < m_imageSize.y(); y++)
1703 for (int x = 0; x < m_imageSize.x(); x++)
1704 {
1705 tcu::Vec4 color = tcu::Vec4(1.0f);
1706
1707 if (m_useDifferentAreasSampleWrite && (x < m_imageSize.x() / 2))
1708 color = m_texture->getLevel(0, 0).getPixel(x + (m_imageSize.x() / 2), y, z) + tcu::Vec4(0.1f);
1709 else
1710 color = m_texture->getLevel(0, 0).getPixel(x, y, z);
1711
1712 if (!m_useDifferentAreasSampleWrite)
1713 color += tcu::Vec4(0.1f);
1714
1715 if (m_interleaveReadWriteComponents)
1716 {
1717 tcu::Vec4 sampledColor = m_texture->getLevel(0, 0).getPixel(x, y, z);
1718 color.x() = color.y();
1719 color.y() = sampledColor.y();
1720 color.z() = color.w();
1721 color.w() = sampledColor.w();
1722 }
1723
1724 color.x() = deFloatClamp(color.x(), 0.0f, 1.0f);
1725 color.y() = deFloatClamp(color.y(), 0.0f, 1.0f);
1726 color.z() = deFloatClamp(color.z(), 0.0f, 1.0f);
1727 color.w() = deFloatClamp(color.w(), 0.0f, 1.0f);
1728
1729 referenceTextureLevel->getAccess().setPixel(color, x, y, z);
1730 }
1731
1732 for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx)
1733 {
1734 // Read back result image
1735 de::MovePtr<tcu::TextureLevel> resultTexture(readColorAttachment(
1736 m_context.getDeviceInterface(), m_context.getDevice(), m_context.getUniversalQueue(),
1737 m_context.getUniversalQueueFamilyIndex(), m_context.getDefaultAllocator(), **m_colorImages[imgNdx],
1738 m_colorFormat, renderSize, vk::VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT));
1739 const tcu::ConstPixelBufferAccess result = resultTexture->getAccess();
1740 const bool isIntegerFormat = isUintFormat(m_imageFormat) || isIntFormat(m_imageFormat);
1741
1742 if (!isIntegerFormat)
1743 {
1744 if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison",
1745 referenceTextureLevel->getAccess(), result, fThreshold,
1746 tcu::COMPARE_LOG_RESULT))
1747 return tcu::TestStatus::fail("Failed color");
1748 }
1749 else
1750 {
1751 if (!tcu::intThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison",
1752 referenceTextureLevel->getAccess(), result, uThreshold,
1753 tcu::COMPARE_LOG_RESULT))
1754 return tcu::TestStatus::fail("Failed color");
1755 }
1756 }
1757
1758 return tcu::TestStatus::pass("Pass");
1759 }
1760
~AttachmentFeedbackLoopLayoutImageSamplingInstance(void)1761 AttachmentFeedbackLoopLayoutImageSamplingInstance::~AttachmentFeedbackLoopLayoutImageSamplingInstance(void)
1762 {
1763 }
1764
iterate(void)1765 tcu::TestStatus AttachmentFeedbackLoopLayoutImageSamplingInstance::iterate(void)
1766 {
1767 const DeviceInterface &vk = m_context.getDeviceInterface();
1768 const VkDevice vkDevice = m_context.getDevice();
1769 const VkQueue queue = m_context.getUniversalQueue();
1770
1771 setup();
1772 submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
1773
1774 return verifyImage();
1775 }
1776
1777 class AttachmentFeedbackLoopLayoutSamplerTest : public vkt::TestCase
1778 {
1779 public:
1780 AttachmentFeedbackLoopLayoutSamplerTest(tcu::TestContext &testContext,
1781 vk::PipelineConstructionType pipelineConstructionType, const char *name,
1782 SamplerViewType imageViewType, VkFormat imageFormat, int imageSize,
1783 VkDescriptorType imageDescriptorType, float samplerLod, TestMode testMode,
1784 ImageAspectTestMode imageAspectTestMode, bool interleaveReadWriteComponents,
1785 PipelineStateMode pipelineStateMode, bool useMaintenance5);
~AttachmentFeedbackLoopLayoutSamplerTest(void)1786 virtual ~AttachmentFeedbackLoopLayoutSamplerTest(void)
1787 {
1788 }
1789
1790 virtual ImageSamplingInstanceParams getImageSamplingInstanceParams(SamplerViewType imageViewType,
1791 VkFormat imageFormat, int imageSize,
1792 VkDescriptorType imageDescriptorType,
1793 float samplerLod) const;
1794
1795 virtual void initPrograms(SourceCollections &sourceCollections) const;
1796 virtual void checkSupport(Context &context) const;
1797 virtual TestInstance *createInstance(Context &context) const;
1798 virtual tcu::UVec2 getRenderSize(SamplerViewType viewType) const;
1799 virtual std::vector<Vertex4Tex4> createVertices(void) const;
1800 virtual VkSamplerCreateInfo getSamplerCreateInfo(void) const;
1801 virtual VkComponentMapping getComponentMapping(void) const;
1802
1803 static std::string getGlslSamplerType(const tcu::TextureFormat &format, SamplerViewType type);
1804 static tcu::IVec3 getImageSize(SamplerViewType viewType, int size);
1805 static int getArraySize(SamplerViewType viewType);
1806
1807 static std::string getGlslSampler(const tcu::TextureFormat &format, VkImageViewType type,
1808 VkDescriptorType samplingType, int imageCount);
1809 static std::string getGlslTextureType(const tcu::TextureFormat &format, VkImageViewType type);
1810 static std::string getGlslSamplerDecl(int imageCount);
1811 static std::string getGlslTextureDecl(int imageCount);
1812
1813 protected:
1814 vk::PipelineConstructionType m_pipelineConstructionType;
1815 SamplerViewType m_imageViewType;
1816 VkFormat m_imageFormat;
1817 int m_imageSize;
1818 VkDescriptorType m_imageDescriptorType;
1819 float m_samplerLod;
1820 TestMode m_testMode;
1821 ImageAspectTestMode m_imageAspectTestMode;
1822 bool m_interleaveReadWriteComponents;
1823 PipelineStateMode m_pipelineStateMode;
1824 bool m_useMaintenance5;
1825 };
1826
1827 // AttachmentFeedbackLoopLayoutSamplerTest
1828
AttachmentFeedbackLoopLayoutSamplerTest(tcu::TestContext & testContext,vk::PipelineConstructionType pipelineConstructionType,const char * name,SamplerViewType imageViewType,VkFormat imageFormat,int imageSize,VkDescriptorType imageDescriptorType,float samplerLod,TestMode testMode,ImageAspectTestMode imageAspectTestMode,bool interleaveReadWriteComponents,PipelineStateMode pipelineStateMode,bool useMaintenance5)1829 AttachmentFeedbackLoopLayoutSamplerTest::AttachmentFeedbackLoopLayoutSamplerTest(
1830 tcu::TestContext &testContext, vk::PipelineConstructionType pipelineConstructionType, const char *name,
1831 SamplerViewType imageViewType, VkFormat imageFormat, int imageSize, VkDescriptorType imageDescriptorType,
1832 float samplerLod, TestMode testMode, ImageAspectTestMode imageAspectTestMode, bool interleaveReadWriteComponents,
1833 PipelineStateMode pipelineStateMode, bool useMaintenance5)
1834 : vkt::TestCase(testContext, name)
1835 , m_pipelineConstructionType(pipelineConstructionType)
1836 , m_imageViewType(imageViewType)
1837 , m_imageFormat(imageFormat)
1838 , m_imageSize(imageSize)
1839 , m_imageDescriptorType(imageDescriptorType)
1840 , m_samplerLod(samplerLod)
1841 , m_testMode(testMode)
1842 , m_imageAspectTestMode(imageAspectTestMode)
1843 , m_interleaveReadWriteComponents(interleaveReadWriteComponents)
1844 , m_pipelineStateMode(pipelineStateMode)
1845 , m_useMaintenance5(useMaintenance5)
1846 {
1847 }
1848
getImageSamplingInstanceParams(SamplerViewType imageViewType,VkFormat imageFormat,int imageSize,VkDescriptorType imageDescriptorType,float samplerLod) const1849 ImageSamplingInstanceParams AttachmentFeedbackLoopLayoutSamplerTest::getImageSamplingInstanceParams(
1850 SamplerViewType imageViewType, VkFormat imageFormat, int imageSize, VkDescriptorType imageDescriptorType,
1851 float samplerLod) const
1852 {
1853 const tcu::UVec2 renderSize = getRenderSize(imageViewType);
1854 const std::vector<Vertex4Tex4> vertices = createVertices();
1855 const VkSamplerCreateInfo samplerParams = getSamplerCreateInfo();
1856 const VkComponentMapping componentMapping = getComponentMapping();
1857
1858 VkImageAspectFlags imageAspect = 0u;
1859 VkPipelineCreateFlags pipelineCreateFlags = 0u;
1860
1861 if (!isCompressedFormat(imageFormat))
1862 {
1863 if (m_imageAspectTestMode == IMAGE_ASPECT_TEST_COLOR)
1864 {
1865 DE_ASSERT(!tcu::hasDepthComponent(mapVkFormat(imageFormat).order) &&
1866 !tcu::hasStencilComponent(mapVkFormat(imageFormat).order));
1867 }
1868 else if (m_imageAspectTestMode == IMAGE_ASPECT_TEST_DEPTH)
1869 DE_ASSERT(tcu::hasDepthComponent(mapVkFormat(imageFormat).order));
1870 else if (m_imageAspectTestMode == IMAGE_ASPECT_TEST_STENCIL)
1871 DE_ASSERT(tcu::hasStencilComponent(mapVkFormat(imageFormat).order));
1872
1873 imageAspect = testModeToAspectFlags(m_imageAspectTestMode);
1874 pipelineCreateFlags = getStaticPipelineCreateFlags(imageAspect, m_pipelineStateMode);
1875 }
1876 else
1877 {
1878 imageAspect = VK_IMAGE_ASPECT_COLOR_BIT;
1879 }
1880
1881 const VkImageSubresourceRange subresourceRange = {
1882 imageAspect, // VkImageAspectFlags aspectMask;
1883 0u, // uint32_t baseMipLevel;
1884 1u, // uint32_t mipLevels;
1885 0u, // uint32_t baseArrayLayer;
1886 (uint32_t)getArraySize(imageViewType) // uint32_t arraySize;
1887 };
1888
1889 return ImageSamplingInstanceParams(m_pipelineConstructionType, renderSize, imageViewType, imageFormat,
1890 getImageSize(imageViewType, imageSize), getArraySize(imageViewType),
1891 componentMapping, subresourceRange, samplerParams, samplerLod, vertices, false,
1892 imageDescriptorType, 1u, ALLOCATION_KIND_SUBALLOCATED,
1893 vk::VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT, pipelineCreateFlags);
1894 }
1895
checkSupport(Context & context) const1896 void AttachmentFeedbackLoopLayoutSamplerTest::checkSupport(Context &context) const
1897 {
1898 const auto &vki = context.getInstanceInterface();
1899 const auto physicalDevice = context.getPhysicalDevice();
1900
1901 checkPipelineConstructionRequirements(vki, physicalDevice, m_pipelineConstructionType);
1902
1903 context.requireDeviceFunctionality("VK_EXT_attachment_feedback_loop_layout");
1904
1905 if (m_useMaintenance5)
1906 context.requireDeviceFunctionality("VK_KHR_maintenance5");
1907
1908 if (m_pipelineStateMode != PipelineStateMode::STATIC || isConstructionTypeShaderObject(m_pipelineConstructionType))
1909 context.requireDeviceFunctionality("VK_EXT_attachment_feedback_loop_dynamic_state");
1910
1911 const auto imgParams = getImageSamplingInstanceParams(m_imageViewType, m_imageFormat, m_imageSize,
1912 m_imageDescriptorType, m_samplerLod);
1913 checkSupportImageSamplingInstance(context, imgParams);
1914
1915 if (m_testMode >= TEST_MODE_READ_WRITE_SAME_PIXEL) // Image as color or DS attachment.
1916 {
1917 VkFormatProperties formatProps;
1918 vki.getPhysicalDeviceFormatProperties(physicalDevice, imgParams.imageFormat, &formatProps);
1919
1920 const auto attachmentFormatFeature = isDepthStencilFormat(imgParams.imageFormat) ?
1921 VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT :
1922 VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
1923 const VkFormatFeatureFlags neededFeatures = attachmentFormatFeature | VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
1924 VK_FORMAT_FEATURE_TRANSFER_SRC_BIT |
1925 VK_FORMAT_FEATURE_TRANSFER_DST_BIT;
1926
1927 if ((formatProps.optimalTilingFeatures & neededFeatures) != neededFeatures)
1928 {
1929 std::ostringstream msg;
1930 msg << "Format does not support required features: 0x" << std::hex << neededFeatures;
1931 TCU_THROW(NotSupportedError, msg.str());
1932 }
1933
1934 if ((!m_interleaveReadWriteComponents && m_imageAspectTestMode == IMAGE_ASPECT_TEST_STENCIL) ||
1935 (m_interleaveReadWriteComponents && m_imageAspectTestMode == IMAGE_ASPECT_TEST_DEPTH))
1936 context.requireDeviceFunctionality("VK_EXT_shader_stencil_export");
1937 }
1938 }
1939
getGlslTextureType(const tcu::TextureFormat & format,VkImageViewType type)1940 std::string AttachmentFeedbackLoopLayoutSamplerTest::getGlslTextureType(const tcu::TextureFormat &format,
1941 VkImageViewType type)
1942 {
1943 std::ostringstream textureType;
1944
1945 if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
1946 textureType << "u";
1947 else if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)
1948 textureType << "i";
1949
1950 switch (type)
1951 {
1952 case VK_IMAGE_VIEW_TYPE_1D:
1953 textureType << "texture1D";
1954 break;
1955
1956 case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
1957 textureType << "texture1DArray";
1958 break;
1959
1960 case VK_IMAGE_VIEW_TYPE_2D:
1961 textureType << "texture2D";
1962 break;
1963
1964 case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
1965 textureType << "texture2DArray";
1966 break;
1967
1968 case VK_IMAGE_VIEW_TYPE_3D:
1969 textureType << "texture3D";
1970 break;
1971
1972 case VK_IMAGE_VIEW_TYPE_CUBE:
1973 textureType << "textureCube";
1974 break;
1975
1976 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
1977 textureType << "textureCubeArray";
1978 break;
1979
1980 default:
1981 DE_FATAL("Unknown image view type");
1982 }
1983
1984 return textureType.str();
1985 }
1986
getGlslSamplerDecl(int imageCount)1987 std::string AttachmentFeedbackLoopLayoutSamplerTest::getGlslSamplerDecl(int imageCount)
1988 {
1989 std::ostringstream samplerArray;
1990 samplerArray << "texSamplers[" << imageCount << "]";
1991
1992 return imageCount > 1 ? samplerArray.str() : "texSampler";
1993 }
1994
getGlslTextureDecl(int imageCount)1995 std::string AttachmentFeedbackLoopLayoutSamplerTest::getGlslTextureDecl(int imageCount)
1996 {
1997 std::ostringstream textureArray;
1998 textureArray << "texImages[" << imageCount << "]";
1999
2000 return imageCount > 1 ? textureArray.str() : "texImage";
2001 }
2002
getGlslSampler(const tcu::TextureFormat & format,VkImageViewType type,VkDescriptorType samplingType,int imageCount)2003 std::string AttachmentFeedbackLoopLayoutSamplerTest::getGlslSampler(const tcu::TextureFormat &format,
2004 VkImageViewType type, VkDescriptorType samplingType,
2005 int imageCount)
2006 {
2007 std::string texSampler = imageCount > 1 ? "texSamplers[i]" : "texSampler";
2008 std::string texImage = imageCount > 1 ? "texImages[i]" : "texImage";
2009
2010 switch (samplingType)
2011 {
2012 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
2013 return getGlslSamplerType(format, type) + "(" + texImage + ", texSampler)";
2014 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
2015 default:
2016 return texSampler;
2017 }
2018 }
2019
initPrograms(SourceCollections & sourceCollections) const2020 void AttachmentFeedbackLoopLayoutSamplerTest::initPrograms(SourceCollections &sourceCollections) const
2021 {
2022 std::ostringstream vertexSrc;
2023 std::ostringstream fragmentSrc;
2024 const char *texCoordSwizzle = DE_NULL;
2025 const VkFormat vkFormat = m_imageAspectTestMode == IMAGE_ASPECT_TEST_STENCIL ? VK_FORMAT_S8_UINT : m_imageFormat;
2026 const tcu::TextureFormat format = (isCompressedFormat(m_imageFormat)) ?
2027 tcu::getUncompressedFormat(mapVkCompressedFormat(vkFormat)) :
2028 mapVkFormat(vkFormat);
2029 tcu::Vec4 lookupScale;
2030 tcu::Vec4 lookupBias;
2031
2032 getLookupScaleBias(m_imageFormat, lookupScale, lookupBias);
2033
2034 switch (m_imageViewType)
2035 {
2036 case VK_IMAGE_VIEW_TYPE_1D:
2037 texCoordSwizzle = "x";
2038 break;
2039 case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
2040 case VK_IMAGE_VIEW_TYPE_2D:
2041 texCoordSwizzle = "xy";
2042 break;
2043 case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
2044 case VK_IMAGE_VIEW_TYPE_3D:
2045 case VK_IMAGE_VIEW_TYPE_CUBE:
2046 texCoordSwizzle = "xyz";
2047 break;
2048 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
2049 texCoordSwizzle = "xyzw";
2050 break;
2051 default:
2052 DE_ASSERT(false);
2053 break;
2054 }
2055
2056 vertexSrc << "#version 440\n"
2057 << "layout(location = 0) in vec4 position;\n"
2058 << "layout(location = 1) in vec4 texCoords;\n"
2059 << "layout(location = 0) out highp vec4 vtxTexCoords;\n"
2060 << "out gl_PerVertex {\n"
2061 << " vec4 gl_Position;\n"
2062 << "};\n"
2063 << "void main (void)\n"
2064 << "{\n"
2065 << " gl_Position = position;\n"
2066 << " vtxTexCoords = texCoords;\n"
2067 << "}\n";
2068
2069 fragmentSrc << "#version 440\n";
2070
2071 if ((m_imageAspectTestMode == IMAGE_ASPECT_TEST_STENCIL && m_testMode >= TEST_MODE_READ_WRITE_SAME_PIXEL) ||
2072 (m_imageAspectTestMode == IMAGE_ASPECT_TEST_DEPTH && m_interleaveReadWriteComponents))
2073 {
2074 fragmentSrc << "#extension GL_ARB_shader_stencil_export: require\n";
2075 }
2076
2077 switch (m_imageDescriptorType)
2078 {
2079 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
2080 fragmentSrc << "layout(set = 0, binding = 0) uniform highp sampler texSampler;\n"
2081 << "layout(set = 0, binding = 1) uniform highp " << getGlslTextureType(format, m_imageViewType)
2082 << " " << getGlslTextureDecl(1u) << ";\n";
2083 break;
2084 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
2085 default:
2086 fragmentSrc << "layout(set = 0, binding = 0) uniform highp " << getGlslSamplerType(format, m_imageViewType)
2087 << " " << getGlslSamplerDecl(1u) << ";\n";
2088 }
2089
2090 if (m_imageAspectTestMode == IMAGE_ASPECT_TEST_COLOR || m_testMode == TEST_MODE_READ_ONLY)
2091 fragmentSrc << "layout(location = 0) out highp vec4 fragColor;\n";
2092
2093 fragmentSrc << "layout(location = 0) in highp vec4 vtxTexCoords;\n"
2094 << "void main (void)\n"
2095 << "{\n";
2096
2097 if (m_imageAspectTestMode == IMAGE_ASPECT_TEST_STENCIL && m_testMode != TEST_MODE_READ_ONLY)
2098 fragmentSrc << " uvec4 read_data = ";
2099 else
2100 fragmentSrc << " vec4 read_data = ";
2101
2102 if (m_imageAspectTestMode == IMAGE_ASPECT_TEST_DEPTH && m_testMode >= TEST_MODE_READ_WRITE_SAME_PIXEL)
2103 {
2104 fragmentSrc << "vec4(1.0f, 0.0f, 0.0f, 1.0f);\n";
2105
2106 fragmentSrc << " read_data.x = ";
2107 if (m_samplerLod > 0.0f)
2108 {
2109 DE_ASSERT(m_imageViewType.isNormalized());
2110 fragmentSrc << "textureLod(" << getGlslSampler(format, m_imageViewType, m_imageDescriptorType, 1u)
2111 << ", vtxTexCoords." << texCoordSwizzle << ", " << std::fixed << m_samplerLod << ").x";
2112 }
2113 else
2114 {
2115 if (m_imageViewType.isNormalized())
2116 fragmentSrc << "texture(" << getGlslSampler(format, m_imageViewType, m_imageDescriptorType, 1u)
2117 << ", vtxTexCoords." << texCoordSwizzle << ").x" << std::fixed;
2118 else
2119 fragmentSrc << "textureLod(" << getGlslSampler(format, m_imageViewType, m_imageDescriptorType, 1u)
2120 << ", vtxTexCoords." << texCoordSwizzle << ", 0).x" << std::fixed;
2121 }
2122
2123 fragmentSrc << " + 0.1f;\n";
2124 }
2125 else if (m_imageAspectTestMode == IMAGE_ASPECT_TEST_STENCIL && m_testMode == TEST_MODE_READ_ONLY)
2126 {
2127 if (m_samplerLod > 0.0f)
2128 {
2129 DE_ASSERT(m_imageViewType.isNormalized());
2130 fragmentSrc << "vec4(textureLod(" << getGlslSampler(format, m_imageViewType, m_imageDescriptorType, 1u)
2131 << ", vtxTexCoords." << texCoordSwizzle << ", " << std::fixed << m_samplerLod
2132 << ").x / 255.0f, 0.0f, 0.0f, 1.0f)";
2133 }
2134 else
2135 {
2136 if (m_imageViewType.isNormalized())
2137 fragmentSrc << "vec4(texture(" << getGlslSampler(format, m_imageViewType, m_imageDescriptorType, 1u)
2138 << ", vtxTexCoords." << texCoordSwizzle << ").x / 255.0f, 0.0f, 0.0f, 1.0f)" << std::fixed;
2139 else
2140 fragmentSrc << "vec4(textureLod(" << getGlslSampler(format, m_imageViewType, m_imageDescriptorType, 1u)
2141 << ", vtxTexCoords." << texCoordSwizzle << ", 0).x / 255.0f, 0.0f, 0.0f, 1.0f)"
2142 << std::fixed;
2143 }
2144
2145 fragmentSrc << ";\n";
2146 }
2147 else
2148 {
2149 if (m_samplerLod > 0.0f)
2150 {
2151 DE_ASSERT(m_imageViewType.isNormalized());
2152 fragmentSrc << "textureLod(" << getGlslSampler(format, m_imageViewType, m_imageDescriptorType, 1u)
2153 << ", vtxTexCoords." << texCoordSwizzle << ", " << std::fixed << m_samplerLod << ")";
2154 }
2155 else
2156 {
2157 if (m_imageViewType.isNormalized())
2158 fragmentSrc << "texture(" << getGlslSampler(format, m_imageViewType, m_imageDescriptorType, 1u)
2159 << ", vtxTexCoords." << texCoordSwizzle << ")" << std::fixed;
2160 else
2161 fragmentSrc << "textureLod(" << getGlslSampler(format, m_imageViewType, m_imageDescriptorType, 1u)
2162 << ", vtxTexCoords." << texCoordSwizzle << ", 0)" << std::fixed;
2163 }
2164
2165 if (m_testMode >= TEST_MODE_READ_WRITE_SAME_PIXEL)
2166 {
2167 if (m_imageAspectTestMode == IMAGE_ASPECT_TEST_STENCIL)
2168 fragmentSrc << " + uvec4(1u, 0u, 0u, 0)";
2169 else
2170 fragmentSrc << " + vec4(0.1f)";
2171 }
2172
2173 fragmentSrc << ";\n";
2174 }
2175
2176 if (m_interleaveReadWriteComponents)
2177 {
2178 if (m_imageAspectTestMode == IMAGE_ASPECT_TEST_COLOR)
2179 {
2180 fragmentSrc << " fragColor = vec4(1.0f);\n"
2181 << " fragColor.x = read_data.y;\n"
2182 << " fragColor.z = read_data.w;\n";
2183 }
2184 else if (m_imageAspectTestMode == IMAGE_ASPECT_TEST_DEPTH)
2185 {
2186 fragmentSrc << " gl_FragStencilRefARB = int(clamp(read_data.x * 255.0f, 0.0f, 255.0f));\n";
2187 }
2188 else
2189 {
2190 fragmentSrc << " gl_FragDepth = clamp(float(read_data.x) / 255.0f, 0.0f, 1.0f);\n";
2191 }
2192 }
2193 else
2194 {
2195 if (m_imageAspectTestMode == IMAGE_ASPECT_TEST_DEPTH && m_testMode >= TEST_MODE_READ_WRITE_SAME_PIXEL)
2196 {
2197 fragmentSrc << " gl_FragDepth = clamp(read_data.x, 0.0f, 1.0f);\n";
2198 }
2199 else if (m_imageAspectTestMode == IMAGE_ASPECT_TEST_STENCIL && m_testMode >= TEST_MODE_READ_WRITE_SAME_PIXEL)
2200 {
2201 fragmentSrc << " gl_FragStencilRefARB = int(clamp(read_data.x, 0u, 255u));\n";
2202 }
2203 else
2204 {
2205 fragmentSrc << " fragColor = read_data;\n";
2206 }
2207 }
2208
2209 fragmentSrc << "}\n";
2210
2211 sourceCollections.glslSources.add("tex_vert") << glu::VertexSource(vertexSrc.str());
2212 sourceCollections.glslSources.add("tex_frag") << glu::FragmentSource(fragmentSrc.str());
2213 }
2214
createInstance(Context & context) const2215 TestInstance *AttachmentFeedbackLoopLayoutSamplerTest::createInstance(Context &context) const
2216 {
2217 const bool useImageAsColorOrDSAttachment = m_testMode >= TEST_MODE_READ_WRITE_SAME_PIXEL;
2218 const bool useDifferentAreasSampleWrite = m_testMode == TEST_MODE_READ_WRITE_DIFFERENT_AREAS;
2219
2220 if (m_imageAspectTestMode != IMAGE_ASPECT_TEST_COLOR && useImageAsColorOrDSAttachment)
2221 return new AttachmentFeedbackLoopLayoutDepthStencilImageSamplingInstance(
2222 context,
2223 getImageSamplingInstanceParams(m_imageViewType, m_imageFormat, m_imageSize, m_imageDescriptorType,
2224 m_samplerLod),
2225 useImageAsColorOrDSAttachment, useDifferentAreasSampleWrite, m_interleaveReadWriteComponents,
2226 m_imageAspectTestMode, m_pipelineStateMode, m_useMaintenance5);
2227 return new AttachmentFeedbackLoopLayoutImageSamplingInstance(
2228 context,
2229 getImageSamplingInstanceParams(m_imageViewType, m_imageFormat, m_imageSize, m_imageDescriptorType,
2230 m_samplerLod),
2231 useImageAsColorOrDSAttachment, useDifferentAreasSampleWrite, m_interleaveReadWriteComponents,
2232 m_imageAspectTestMode, m_pipelineStateMode, m_useMaintenance5);
2233 }
2234
getRenderSize(SamplerViewType viewType) const2235 tcu::UVec2 AttachmentFeedbackLoopLayoutSamplerTest::getRenderSize(SamplerViewType viewType) const
2236 {
2237 if (viewType == VK_IMAGE_VIEW_TYPE_1D || viewType == VK_IMAGE_VIEW_TYPE_2D)
2238 {
2239 return tcu::UVec2(16u, 16u);
2240 }
2241 else
2242 {
2243 return tcu::UVec2(16u * 3u, 16u * 2u);
2244 }
2245 }
2246
createFullscreenQuadArray(vk::VkImageViewType viewType,unsigned arraySize)2247 std::vector<Vertex4Tex4> createFullscreenQuadArray(vk::VkImageViewType viewType, unsigned arraySize)
2248 {
2249 using tcu::Vec4;
2250 std::vector<Vertex4Tex4> verticesArray;
2251
2252 const Vertex4Tex4 lowerLeftVertex = {Vec4(-1.0f, -1.0f, 0.0f, 1.0f), Vec4(0.0f, 0.0f, 0.0f, 0.0f)};
2253 const Vertex4Tex4 upperLeftVertex = {Vec4(-1.0f, 1.0f, 0.0f, 1.0f), Vec4(0.0f, 1.0f, 0.0f, 0.0f)};
2254 const Vertex4Tex4 lowerRightVertex = {Vec4(1.0f, -1.0f, 0.0f, 1.0f), Vec4(1.0f, 0.0f, 0.0f, 0.0f)};
2255 const Vertex4Tex4 upperRightVertex = {Vec4(1.0f, 1.0f, 0.0f, 1.0f), Vec4(1.0f, 1.0f, 0.0f, 0.0f)};
2256
2257 for (unsigned arrayNdx = 0; arrayNdx < arraySize; arrayNdx++)
2258 {
2259 Vertex4Tex4 vertices[6] = {lowerLeftVertex, upperLeftVertex, lowerRightVertex,
2260
2261 upperLeftVertex, lowerRightVertex, upperRightVertex};
2262
2263 for (int i = 0; i < 6; i++)
2264 {
2265 if (viewType == vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY)
2266 {
2267 vertices[i].position.y() = (float)arrayNdx;
2268 vertices[i].texCoord.y() = (float)arrayNdx;
2269 }
2270 else
2271 {
2272 vertices[i].position.z() = (float)arrayNdx;
2273 vertices[i].texCoord.z() = (float)arrayNdx;
2274 }
2275 verticesArray.push_back(vertices[i]);
2276 }
2277 }
2278
2279 return verticesArray;
2280 }
2281
createTestQuadAttachmentFeedbackLoopLayout(vk::VkImageViewType viewType)2282 std::vector<Vertex4Tex4> createTestQuadAttachmentFeedbackLoopLayout(vk::VkImageViewType viewType)
2283 {
2284 std::vector<Vertex4Tex4> vertices;
2285
2286 switch (viewType)
2287 {
2288 case vk::VK_IMAGE_VIEW_TYPE_1D:
2289 case vk::VK_IMAGE_VIEW_TYPE_2D:
2290 vertices = createFullscreenQuad();
2291 break;
2292
2293 case vk::VK_IMAGE_VIEW_TYPE_1D_ARRAY:
2294 vertices = createFullscreenQuadArray(viewType, 6u);
2295 break;
2296
2297 case vk::VK_IMAGE_VIEW_TYPE_2D_ARRAY:
2298 case vk::VK_IMAGE_VIEW_TYPE_3D:
2299 case vk::VK_IMAGE_VIEW_TYPE_CUBE:
2300 case vk::VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
2301 vertices = createFullscreenQuadArray(viewType, 6u);
2302 break;
2303
2304 default:
2305 DE_ASSERT(false);
2306 break;
2307 }
2308
2309 return vertices;
2310 }
2311
createVertices(void) const2312 std::vector<Vertex4Tex4> AttachmentFeedbackLoopLayoutSamplerTest::createVertices(void) const
2313 {
2314 std::vector<Vertex4Tex4> vertices = m_testMode != TEST_MODE_READ_WRITE_DIFFERENT_AREAS ?
2315 createTestQuadMosaic(m_imageViewType) :
2316 createTestQuadAttachmentFeedbackLoopLayout(m_imageViewType);
2317 for (unsigned int i = 0; i < vertices.size(); ++i)
2318 {
2319 if (m_testMode == TEST_MODE_READ_WRITE_DIFFERENT_AREAS)
2320 {
2321 vertices[i].texCoord.x() = std::max(vertices[i].texCoord.x(), 0.5f);
2322 vertices[i].position.x() = std::min(vertices[i].position.x(), 0.0f);
2323 }
2324 if (!m_imageViewType.isNormalized())
2325 {
2326 const float imageSize = static_cast<float>(m_imageSize);
2327 for (int j = 0; j < tcu::Vec4::SIZE; ++j)
2328 vertices[i].texCoord[j] *= imageSize;
2329 }
2330 }
2331 return vertices;
2332 }
2333
getSamplerCreateInfo(void) const2334 VkSamplerCreateInfo AttachmentFeedbackLoopLayoutSamplerTest::getSamplerCreateInfo(void) const
2335 {
2336 const VkSamplerCreateInfo defaultSamplerParams = {
2337 VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // VkStructureType sType;
2338 DE_NULL, // const void* pNext;
2339 0u, // VkSamplerCreateFlags flags;
2340 VK_FILTER_NEAREST, // VkFilter magFilter;
2341 VK_FILTER_NEAREST, // VkFilter minFilter;
2342 VK_SAMPLER_MIPMAP_MODE_NEAREST, // VkSamplerMipmapMode mipmapMode;
2343 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeU;
2344 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeV;
2345 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeW;
2346 0.0f, // float mipLodBias;
2347 VK_FALSE, // VkBool32 anisotropyEnable;
2348 1.0f, // float maxAnisotropy;
2349 false, // VkBool32 compareEnable;
2350 VK_COMPARE_OP_NEVER, // VkCompareOp compareOp;
2351 0.0f, // float minLod;
2352 (m_imageViewType.isNormalized() ? 0.25f : 0.0f), // float maxLod;
2353 getFormatBorderColor(BORDER_COLOR_TRANSPARENT_BLACK, m_imageFormat,
2354 false), // VkBorderColor borderColor;
2355 !m_imageViewType.isNormalized(), // VkBool32 unnormalizedCoordinates;
2356 };
2357
2358 return defaultSamplerParams;
2359 }
2360
getComponentMapping(void) const2361 VkComponentMapping AttachmentFeedbackLoopLayoutSamplerTest::getComponentMapping(void) const
2362 {
2363 const VkComponentMapping componentMapping = {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B,
2364 VK_COMPONENT_SWIZZLE_A};
2365 return componentMapping;
2366 }
2367
getGlslSamplerType(const tcu::TextureFormat & format,SamplerViewType type)2368 std::string AttachmentFeedbackLoopLayoutSamplerTest::getGlslSamplerType(const tcu::TextureFormat &format,
2369 SamplerViewType type)
2370 {
2371 std::ostringstream samplerType;
2372
2373 if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
2374 samplerType << "u";
2375 else if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)
2376 samplerType << "i";
2377
2378 switch (type)
2379 {
2380 case VK_IMAGE_VIEW_TYPE_1D:
2381 samplerType << "sampler1D";
2382 break;
2383
2384 case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
2385 samplerType << "sampler1DArray";
2386 break;
2387
2388 case VK_IMAGE_VIEW_TYPE_2D:
2389 samplerType << "sampler2D";
2390 break;
2391
2392 case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
2393 samplerType << "sampler2DArray";
2394 break;
2395
2396 case VK_IMAGE_VIEW_TYPE_3D:
2397 samplerType << "sampler3D";
2398 break;
2399
2400 case VK_IMAGE_VIEW_TYPE_CUBE:
2401 samplerType << "samplerCube";
2402 break;
2403
2404 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
2405 samplerType << "samplerCubeArray";
2406 break;
2407
2408 default:
2409 DE_FATAL("Unknown image view type");
2410 break;
2411 }
2412
2413 return samplerType.str();
2414 }
2415
getImageSize(SamplerViewType viewType,int size)2416 tcu::IVec3 AttachmentFeedbackLoopLayoutSamplerTest::getImageSize(SamplerViewType viewType, int size)
2417 {
2418 switch (viewType)
2419 {
2420 case VK_IMAGE_VIEW_TYPE_1D:
2421 case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
2422 return tcu::IVec3(size, 1, 1);
2423
2424 case VK_IMAGE_VIEW_TYPE_3D:
2425 return tcu::IVec3(size, size, 4);
2426
2427 default:
2428 break;
2429 }
2430
2431 return tcu::IVec3(size, size, 1);
2432 }
2433
getArraySize(SamplerViewType viewType)2434 int AttachmentFeedbackLoopLayoutSamplerTest::getArraySize(SamplerViewType viewType)
2435 {
2436 switch (viewType)
2437 {
2438 case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
2439 case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
2440 case VK_IMAGE_VIEW_TYPE_CUBE:
2441 return 6;
2442
2443 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
2444 return 36;
2445
2446 default:
2447 break;
2448 }
2449
2450 return 1;
2451 }
2452
2453 // The idea behind this test is to reproduce a behavior that was causing GPU hangs on RADV.
2454 // * create a color attachment
2455 // * transition from UNDEFINED to COLOR_ATTACHMENT_OPTIMAL
2456 // * draw something
2457 // * transition from COLOR_ATTACHMENT_OPTIMAL to ATTACHMENT_FEEDBACK_LOOP_OPTIMAL
2458 // * draw something with a pipeline that has 0 color attachments
2459 // * GPU hanged
noColorAttachmentSupport(Context & context)2460 void noColorAttachmentSupport(Context &context)
2461 {
2462 context.requireDeviceFunctionality("VK_EXT_attachment_feedback_loop_layout");
2463 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_FRAGMENT_STORES_AND_ATOMICS);
2464 }
2465
noColorAttachmentPrograms(SourceCollections & dst)2466 void noColorAttachmentPrograms(SourceCollections &dst)
2467 {
2468 std::ostringstream vert;
2469 vert << "#version 460\n"
2470 << "layout (location=0) in vec4 inPos;\n"
2471 << "void main (void) {\n"
2472 << " gl_Position = inPos;\n"
2473 << "}\n";
2474 dst.glslSources.add("vert") << glu::VertexSource(vert.str());
2475
2476 // For the initial draw, simple color.
2477 std::ostringstream frag1;
2478 frag1 << "#version 460\n"
2479 << "layout (location=0) out vec4 outColor;\n"
2480 << "layout (push_constant, std430) uniform PushConstantBlock {\n"
2481 << " vec4 color;\n"
2482 << "} pc;\n"
2483 << "void main (void) {\n"
2484 << " outColor = pc.color;\n"
2485 << "}\n";
2486 dst.glslSources.add("frag1") << glu::FragmentSource(frag1.str());
2487
2488 // For the second draw, store without color attachments.
2489 std::ostringstream frag2;
2490 frag2 << "#version 460\n"
2491 << "layout (set=0, binding=0, std430) buffer BufferBlock {\n"
2492 << " uint value;\n"
2493 << "} outBuffer;\n"
2494 << "void main (void) {\n"
2495 << " atomicAdd(outBuffer.value, 1u);\n"
2496 << "}\n";
2497 dst.glslSources.add("frag2") << glu::FragmentSource(frag2.str());
2498 }
2499
noColorAttachmentTest(Context & context)2500 tcu::TestStatus noColorAttachmentTest(Context &context)
2501 {
2502 const auto &ctx = context.getContextCommonData();
2503 const tcu::IVec3 fbExtent(544, 544, 1); // The image needs to be large-ish.
2504 const auto vkExtent = makeExtent3D(fbExtent);
2505 const auto fbFormat = VK_FORMAT_R8G8B8A8_UNORM;
2506 const auto tcuFormat = mapVkFormat(fbFormat);
2507 const auto fbUsage = (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
2508 VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT);
2509 const tcu::Vec4 clearColor(0.0f, 0.0f, 0.0f, 1.0f);
2510 const tcu::Vec4 geomColor1(0.0f, 0.0f, 1.0f, 1.0f);
2511 const tcu::Vec4 geomColor2(1.0f, 0.0f, 1.0f, 1.0f);
2512 const tcu::Vec4 threshold(0.0f, 0.0f, 0.0f, 0.0f); // When using 0 and 1 only, we expect exact results.
2513 const auto descType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
2514 const auto bindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
2515 const auto dataStages = VK_SHADER_STAGE_FRAGMENT_BIT;
2516 const auto colorSRR = makeDefaultImageSubresourceRange();
2517
2518 // Color buffer with verification buffer.
2519 ImageWithBuffer colorBuffer1(ctx.vkd, ctx.device, ctx.allocator, vkExtent, fbFormat, fbUsage, VK_IMAGE_TYPE_2D);
2520
2521 // Second color buffer with verification buffer.
2522 ImageWithBuffer colorBuffer2(ctx.vkd, ctx.device, ctx.allocator, vkExtent, fbFormat, fbUsage, VK_IMAGE_TYPE_2D);
2523
2524 // Vertices.
2525 const std::vector<tcu::Vec4> vertices{
2526 tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f),
2527 tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f),
2528 tcu::Vec4(1.0f, -1.0f, 0.0f, 1.0f),
2529 tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f),
2530 };
2531
2532 // Indices.
2533 const std::vector<uint32_t> indices{
2534 0u, 1u, 2u, 2u, 1u, 3u,
2535 };
2536
2537 // Vertex buffer
2538 const auto vbSize = static_cast<VkDeviceSize>(de::dataSize(vertices));
2539 const auto vbInfo = makeBufferCreateInfo(vbSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
2540 BufferWithMemory vertexBuffer(ctx.vkd, ctx.device, ctx.allocator, vbInfo, MemoryRequirement::HostVisible);
2541 const auto vbAlloc = vertexBuffer.getAllocation();
2542 void *vbData = vbAlloc.getHostPtr();
2543 const auto vbOffset = static_cast<VkDeviceSize>(0);
2544
2545 deMemcpy(vbData, de::dataOrNull(vertices), de::dataSize(vertices));
2546 flushAlloc(ctx.vkd, ctx.device, vbAlloc);
2547
2548 // Index buffer.
2549 const auto ibSize = static_cast<VkDeviceSize>(de::dataSize(indices));
2550 const auto ibInfo = makeBufferCreateInfo(ibSize, VK_BUFFER_USAGE_INDEX_BUFFER_BIT);
2551 BufferWithMemory indexBuffer(ctx.vkd, ctx.device, ctx.allocator, ibInfo, MemoryRequirement::HostVisible);
2552 const auto ibAlloc = indexBuffer.getAllocation();
2553 void *ibData = ibAlloc.getHostPtr();
2554 const auto ibOffset = static_cast<VkDeviceSize>(0);
2555
2556 deMemcpy(ibData, de::dataOrNull(indices), de::dataSize(indices));
2557 flushAlloc(ctx.vkd, ctx.device, ibAlloc);
2558
2559 // Data buffer for the second fragment shader.
2560 const auto dbSize = static_cast<VkDeviceSize>(sizeof(uint32_t));
2561 const auto dbInfo = makeBufferCreateInfo(dbSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);
2562 BufferWithMemory dataBuffer(ctx.vkd, ctx.device, ctx.allocator, dbInfo, MemoryRequirement::HostVisible);
2563 const auto dbAlloc = dataBuffer.getAllocation();
2564 void *dbData = dbAlloc.getHostPtr();
2565 const auto dbOffset = static_cast<VkDeviceSize>(0);
2566
2567 deMemset(dbData, 0, sizeof(uint32_t));
2568 flushAlloc(ctx.vkd, ctx.device, dbAlloc);
2569
2570 // Descriptor pool, set, layout, etc.
2571 DescriptorPoolBuilder poolBuilder;
2572 poolBuilder.addType(descType);
2573 const auto descriptorPool =
2574 poolBuilder.build(ctx.vkd, ctx.device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
2575
2576 DescriptorSetLayoutBuilder layoutBuilder;
2577 layoutBuilder.addSingleBinding(descType, dataStages);
2578 const auto setLayout = layoutBuilder.build(ctx.vkd, ctx.device);
2579 const auto descriptorSet = makeDescriptorSet(ctx.vkd, ctx.device, *descriptorPool, *setLayout);
2580
2581 DescriptorSetUpdateBuilder updateBuilder;
2582 const auto dbDescInfo = makeDescriptorBufferInfo(dataBuffer.get(), dbOffset, dbSize);
2583 updateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), descType, &dbDescInfo);
2584 updateBuilder.update(ctx.vkd, ctx.device);
2585
2586 // Push constant for the color attachment pipeline.
2587 const auto pcSize = static_cast<uint32_t>(sizeof(geomColor1));
2588 const auto pcRange = makePushConstantRange(dataStages, 0u, pcSize);
2589
2590 // Two pipeline layouts: one without any descriptor and one with the single descriptor we use.
2591 const auto pipelineLayout1 = makePipelineLayout(ctx.vkd, ctx.device, VK_NULL_HANDLE, &pcRange);
2592 const auto pipelineLayout2 = makePipelineLayout(ctx.vkd, ctx.device, *setLayout);
2593
2594 // Two render passes: one with one color attachment and one empty.
2595 const auto renderPass1 =
2596 makeRenderPass(ctx.vkd, ctx.device, fbFormat, VK_FORMAT_UNDEFINED, VK_ATTACHMENT_LOAD_OP_LOAD);
2597 const auto renderPass2 = makeRenderPass(ctx.vkd, ctx.device);
2598
2599 // Three framebuffers: two with a color attachment and one empty with the same size.
2600 const auto framebuffer1 = makeFramebuffer(ctx.vkd, ctx.device, *renderPass1, colorBuffer1.getImageView(),
2601 vkExtent.width, vkExtent.height);
2602 const auto framebuffer2 =
2603 makeFramebuffer(ctx.vkd, ctx.device, *renderPass2, 0u, nullptr, vkExtent.width, vkExtent.height);
2604 const auto framebuffer3 = makeFramebuffer(ctx.vkd, ctx.device, *renderPass1, colorBuffer2.getImageView(),
2605 vkExtent.width, vkExtent.height);
2606
2607 // Modules.
2608 const auto &binaries = context.getBinaryCollection();
2609 const auto vertModule = createShaderModule(ctx.vkd, ctx.device, binaries.get("vert"));
2610 const auto fragModule1 = createShaderModule(ctx.vkd, ctx.device, binaries.get("frag1"));
2611 const auto fragModule2 = createShaderModule(ctx.vkd, ctx.device, binaries.get("frag2"));
2612
2613 const std::vector<VkViewport> viewports(1u, makeViewport(vkExtent));
2614 const std::vector<VkRect2D> scissors(1u, makeRect2D(vkExtent));
2615
2616 // Two pipelines, with separate modules, layouts and render passes.
2617 const auto pipeline1 = makeGraphicsPipeline(
2618 ctx.vkd, ctx.device, *pipelineLayout1, *vertModule, VK_NULL_HANDLE, VK_NULL_HANDLE, VK_NULL_HANDLE,
2619 *fragModule1, *renderPass1, viewports,
2620 scissors); // The default values work for the current setup, including the vertex input data format.
2621
2622 const auto pipeline2 =
2623 makeGraphicsPipeline(ctx.vkd, ctx.device, *pipelineLayout2, *vertModule, VK_NULL_HANDLE, VK_NULL_HANDLE,
2624 VK_NULL_HANDLE, *fragModule2, *renderPass2, viewports, scissors); // Ditto.
2625
2626 CommandPoolWithBuffer cmd(ctx.vkd, ctx.device, ctx.qfIndex);
2627 const auto cmdBuffer = *cmd.cmdBuffer;
2628
2629 beginCommandBuffer(ctx.vkd, cmdBuffer);
2630
2631 // Transition color buffers to color attachment optimal.
2632 {
2633 const std::vector<VkImage> images{colorBuffer1.getImage(), colorBuffer2.getImage()};
2634 std::vector<VkImageMemoryBarrier> barriers;
2635 barriers.reserve(images.size());
2636
2637 for (const auto &img : images)
2638 {
2639 const auto transitionBarrier = makeImageMemoryBarrier(
2640 0u, (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT),
2641 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, img, colorSRR);
2642 barriers.push_back(transitionBarrier);
2643 }
2644 cmdPipelineImageMemoryBarrier(ctx.vkd, cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
2645 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, de::dataOrNull(barriers),
2646 barriers.size());
2647 }
2648
2649 beginRenderPass(ctx.vkd, cmdBuffer, *renderPass1, *framebuffer1, scissors.at(0u), clearColor);
2650 ctx.vkd.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vbOffset);
2651 ctx.vkd.cmdBindIndexBuffer(cmdBuffer, indexBuffer.get(), ibOffset, VK_INDEX_TYPE_UINT32);
2652 ctx.vkd.cmdBindPipeline(cmdBuffer, bindPoint, *pipeline1);
2653 ctx.vkd.cmdPushConstants(cmdBuffer, *pipelineLayout1, dataStages, 0u, pcSize, &geomColor1);
2654 ctx.vkd.cmdDrawIndexed(cmdBuffer, de::sizeU32(indices), 1u, 0u, 0, 0u);
2655 endRenderPass(ctx.vkd, cmdBuffer);
2656
2657 // Transition first color buffer to feedback loop layout optimal.
2658 {
2659 const auto transitionBarrier = makeImageMemoryBarrier(
2660 (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT), 0u,
2661 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT,
2662 colorBuffer1.getImage(), colorSRR);
2663 cmdPipelineImageMemoryBarrier(ctx.vkd, cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
2664 VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, &transitionBarrier);
2665 }
2666
2667 // Draw with the empty framebuffer and the second pipeline, saving results to the storage buffer.
2668 beginRenderPass(ctx.vkd, cmdBuffer, *renderPass2, *framebuffer2, scissors.at(0u));
2669 ctx.vkd.cmdBindDescriptorSets(cmdBuffer, bindPoint, *pipelineLayout2, 0u, 1u, &descriptorSet.get(), 0u, nullptr);
2670 ctx.vkd.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vbOffset);
2671 ctx.vkd.cmdBindIndexBuffer(cmdBuffer, indexBuffer.get(), ibOffset, VK_INDEX_TYPE_UINT32);
2672 ctx.vkd.cmdBindPipeline(cmdBuffer, bindPoint, *pipeline2);
2673 ctx.vkd.cmdDrawIndexed(cmdBuffer, de::sizeU32(indices), 1u, 0u, 0, 0u);
2674 endRenderPass(ctx.vkd, cmdBuffer);
2675
2676 // Barrier for the storage buffer.
2677 {
2678 const auto frag2hostBarrier = makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
2679 cmdPipelineMemoryBarrier(ctx.vkd, cmdBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
2680 &frag2hostBarrier);
2681 }
2682
2683 #if 0
2684 // Transition color buffer back to color attachment optimal.
2685 {
2686 const auto transitionBarrier = makeImageMemoryBarrier(0u,
2687 (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT),
2688 VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT,
2689 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
2690 colorBuffer1.getImage(), colorSRR);
2691 cmdPipelineImageMemoryBarrier(ctx.vkd, cmdBuffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, &transitionBarrier);
2692 }
2693 #endif
2694
2695 beginRenderPass(ctx.vkd, cmdBuffer, *renderPass1, *framebuffer3, scissors.at(0u), clearColor);
2696 ctx.vkd.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vbOffset);
2697 ctx.vkd.cmdBindIndexBuffer(cmdBuffer, indexBuffer.get(), ibOffset, VK_INDEX_TYPE_UINT32);
2698 ctx.vkd.cmdBindPipeline(cmdBuffer, bindPoint, *pipeline1);
2699 ctx.vkd.cmdPushConstants(cmdBuffer, *pipelineLayout1, dataStages, 0u, pcSize, &geomColor2);
2700 ctx.vkd.cmdDrawIndexed(cmdBuffer, de::sizeU32(indices), 1u, 0u, 0, 0u);
2701 endRenderPass(ctx.vkd, cmdBuffer);
2702
2703 copyImageToBuffer(ctx.vkd, cmdBuffer, colorBuffer1.getImage(), colorBuffer1.getBuffer(), fbExtent.swizzle(0, 1), 0u,
2704 VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT, 1u, VK_IMAGE_ASPECT_COLOR_BIT,
2705 VK_IMAGE_ASPECT_COLOR_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT);
2706
2707 copyImageToBuffer(ctx.vkd, cmdBuffer, colorBuffer2.getImage(), colorBuffer2.getBuffer(), fbExtent.swizzle(0, 1),
2708 (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT),
2709 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 1u, VK_IMAGE_ASPECT_COLOR_BIT,
2710 VK_IMAGE_ASPECT_COLOR_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
2711
2712 endCommandBuffer(ctx.vkd, cmdBuffer);
2713 submitCommandsAndWait(ctx.vkd, ctx.device, ctx.queue, cmdBuffer);
2714
2715 // Verify color outputs.
2716 invalidateAlloc(ctx.vkd, ctx.device, colorBuffer1.getBufferAllocation());
2717 invalidateAlloc(ctx.vkd, ctx.device, colorBuffer2.getBufferAllocation());
2718
2719 tcu::PixelBufferAccess resultAccess1(tcuFormat, fbExtent, colorBuffer1.getBufferAllocation().getHostPtr());
2720 tcu::PixelBufferAccess resultAccess2(tcuFormat, fbExtent, colorBuffer2.getBufferAllocation().getHostPtr());
2721
2722 tcu::TextureLevel referenceLevel1(tcuFormat, fbExtent.x(), fbExtent.y());
2723 auto referenceAccess1 = referenceLevel1.getAccess();
2724 tcu::clear(referenceAccess1, geomColor1);
2725
2726 tcu::TextureLevel referenceLevel2(tcuFormat, fbExtent.x(), fbExtent.y());
2727 auto referenceAccess2 = referenceLevel2.getAccess();
2728 tcu::clear(referenceAccess2, geomColor2);
2729
2730 auto &log = context.getTestContext().getLog();
2731
2732 if (!tcu::floatThresholdCompare(log, "Result", "", referenceAccess1, resultAccess1, threshold,
2733 tcu::COMPARE_LOG_ON_ERROR))
2734 TCU_FAIL("Unexpected color in first result buffer; check log for details");
2735
2736 if (!tcu::floatThresholdCompare(log, "Result", "", referenceAccess2, resultAccess2, threshold,
2737 tcu::COMPARE_LOG_ON_ERROR))
2738 TCU_FAIL("Unexpected color in second result buffer; check log for details");
2739
2740 // Verify storage buffer.
2741 invalidateAlloc(ctx.vkd, ctx.device, dbAlloc);
2742 {
2743 uint32_t outputVal;
2744 const auto expectedVal = vkExtent.width * vkExtent.height;
2745
2746 deMemcpy(&outputVal, dbData, sizeof(outputVal));
2747 if (outputVal != expectedVal)
2748 TCU_FAIL("Unexpected data buffer value: expected " + std::to_string(expectedVal) + " and found " +
2749 std::to_string(outputVal));
2750 }
2751
2752 return tcu::TestStatus::pass("Pass");
2753 }
2754
2755 using TestCaseGroupPtr = de::MovePtr<tcu::TestCaseGroup>;
2756
2757 } // namespace
2758
createAttachmentFeedbackLoopLayoutSamplerTests(tcu::TestContext & testCtx,vk::PipelineConstructionType pipelineConstructionType)2759 tcu::TestCaseGroup *createAttachmentFeedbackLoopLayoutSamplerTests(
2760 tcu::TestContext &testCtx, vk::PipelineConstructionType pipelineConstructionType)
2761 {
2762 // TODO: implement layer rendering with a geometry shader to render to arrays, 3D and cube images.
2763 const struct
2764 {
2765 SamplerViewType type;
2766 const char *name;
2767 bool readOnly;
2768 } imageViewTypes[] = {{VK_IMAGE_VIEW_TYPE_1D, "1d", false},
2769 {{VK_IMAGE_VIEW_TYPE_1D, false}, "1d_unnormalized", false},
2770 {VK_IMAGE_VIEW_TYPE_1D_ARRAY, "1d_array", true},
2771 {VK_IMAGE_VIEW_TYPE_2D, "2d", false},
2772 {{VK_IMAGE_VIEW_TYPE_2D, false}, "2d_unnormalized", false},
2773 {VK_IMAGE_VIEW_TYPE_2D_ARRAY, "2d_array", true},
2774 {VK_IMAGE_VIEW_TYPE_3D, "3d", true},
2775 {VK_IMAGE_VIEW_TYPE_CUBE, "cube", true},
2776 {VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, "cube_array", true}};
2777
2778 const VkFormat formats[] = {
2779 VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_D16_UNORM, VK_FORMAT_D32_SFLOAT, VK_FORMAT_D16_UNORM_S8_UINT,
2780 VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_S8_UINT};
2781
2782 TestCaseGroupPtr samplingTypeTests(new tcu::TestCaseGroup(testCtx, "sampler"));
2783
2784 const struct
2785 {
2786 enum TestMode mode;
2787 const char *name;
2788 } testModes[] = {
2789 {TEST_MODE_READ_ONLY, "_read"},
2790 {TEST_MODE_READ_WRITE_SAME_PIXEL, "_read_write_same_pixel"},
2791 {TEST_MODE_READ_WRITE_DIFFERENT_AREAS, "_read_write_different_areas"},
2792 };
2793
2794 const char *imageAspectTestModes[] = {"_color", "_depth", "_stencil"};
2795
2796 const struct
2797 {
2798 VkDescriptorType type;
2799 const char *name;
2800 } imageDescriptorTypes[] = {
2801 {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, "combined_image_sampler"},
2802 {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, "sampled_image"},
2803 };
2804
2805 const struct
2806 {
2807 bool interleaveReadWriteComponents;
2808 const char *name;
2809 } interleaveReadWriteComponentsModes[] = {
2810 {false, ""},
2811 {true, "_interleave_read_write_components"},
2812 };
2813
2814 const struct
2815 {
2816 const PipelineStateMode pipelineStateMode;
2817 const char *suffix;
2818 } pipelineStateModes[] = {
2819 {PipelineStateMode::STATIC, ""},
2820 {PipelineStateMode::DYNAMIC_WITH_ZERO_STATIC, "_dynamic_zero_static"},
2821 {PipelineStateMode::DYNAMIC_WITH_CONTRADICTORY_STATIC, "_dynamic_bad_static"},
2822 };
2823
2824 for (int imageDescriptorTypeNdx = 0; imageDescriptorTypeNdx < DE_LENGTH_OF_ARRAY(imageDescriptorTypes);
2825 imageDescriptorTypeNdx++)
2826 {
2827 VkDescriptorType imageDescriptorType = imageDescriptorTypes[imageDescriptorTypeNdx].type;
2828 TestCaseGroupPtr imageDescriptorTypeGroup(
2829 new tcu::TestCaseGroup(testCtx, imageDescriptorTypes[imageDescriptorTypeNdx].name));
2830 TestCaseGroupPtr imageTypeTests(new tcu::TestCaseGroup(testCtx, "image_type"));
2831
2832 for (int viewTypeNdx = 0; viewTypeNdx < DE_LENGTH_OF_ARRAY(imageViewTypes); viewTypeNdx++)
2833 {
2834 const SamplerViewType viewType = imageViewTypes[viewTypeNdx].type;
2835 TestCaseGroupPtr viewTypeGroup(new tcu::TestCaseGroup(testCtx, imageViewTypes[viewTypeNdx].name));
2836 TestCaseGroupPtr formatTests(new tcu::TestCaseGroup(testCtx, "format"));
2837
2838 for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
2839 {
2840 const VkFormat format = formats[formatNdx];
2841 const bool isCompressed = isCompressedFormat(format);
2842 const bool isDepthStencil = !isCompressed && tcu::hasDepthComponent(mapVkFormat(format).order) &&
2843 tcu::hasStencilComponent(mapVkFormat(format).order);
2844 ImageAspectTestMode imageAspectTestMode = getImageAspectTestMode(format);
2845
2846 if (isCompressed)
2847 {
2848 // Do not use compressed formats with 1D and 1D array textures.
2849 if (viewType == VK_IMAGE_VIEW_TYPE_1D || viewType == VK_IMAGE_VIEW_TYPE_1D_ARRAY)
2850 break;
2851 }
2852
2853 for (int testModeNdx = 0; testModeNdx < DE_LENGTH_OF_ARRAY(testModes); testModeNdx++)
2854 {
2855 if (imageViewTypes[viewTypeNdx].readOnly && testModes[testModeNdx].mode != TEST_MODE_READ_ONLY)
2856 continue;
2857
2858 for (int restrictColorNdx = 0;
2859 restrictColorNdx < DE_LENGTH_OF_ARRAY(interleaveReadWriteComponentsModes); restrictColorNdx++)
2860 {
2861 // Limit the interleaveReadWriteComponents test to the ones sampling and writing to the same pixel, to avoid having more tests that are not really adding coverage.
2862 if (interleaveReadWriteComponentsModes[restrictColorNdx].interleaveReadWriteComponents &&
2863 testModes[testModeNdx].mode != TEST_MODE_READ_WRITE_SAME_PIXEL)
2864 continue;
2865
2866 // If the format is depth-only or stencil-only, do not read one component and write it to the other, as it is missing.
2867 if (interleaveReadWriteComponentsModes[restrictColorNdx].interleaveReadWriteComponents &&
2868 (tcu::hasDepthComponent(mapVkFormat(format).order) ||
2869 tcu::hasStencilComponent(mapVkFormat(format).order)) &&
2870 !isDepthStencil)
2871 continue;
2872
2873 for (const auto &pipelineStateMode : pipelineStateModes)
2874 {
2875 // In shader object variants of the tests there's no static part, so the
2876 // DYNAMIC_WITH_CONTRADICTORY_STATIC variants serve no purpose. We could keep just one of the variants,
2877 // but we run both a static and a dynamic one because the command sequence is not exactly the same in
2878 // both cases, and the flags used in vkCmdSetAttachmentFeedbackLoopEnableEXT also differ slightly.
2879 //
2880 // The static variant allows us to check a different sequence and that the code in the pipeline
2881 // construction utils is working correctly.
2882 //
2883 // The dynamic variant sets the state later explicitly (see above) and uses more specific aspect flags.
2884 //
2885 if (pipelineStateMode.pipelineStateMode ==
2886 PipelineStateMode::DYNAMIC_WITH_CONTRADICTORY_STATIC &&
2887 isConstructionTypeShaderObject(pipelineConstructionType))
2888 continue;
2889
2890 std::string name = getFormatCaseName(format) + imageAspectTestModes[imageAspectTestMode] +
2891 testModes[testModeNdx].name +
2892 interleaveReadWriteComponentsModes[restrictColorNdx].name +
2893 pipelineStateMode.suffix;
2894 formatTests->addChild(new AttachmentFeedbackLoopLayoutSamplerTest(
2895 testCtx, pipelineConstructionType, name.c_str(), viewType, format, outputImageSize,
2896 imageDescriptorType, 0.0f, testModes[testModeNdx].mode, imageAspectTestMode,
2897 interleaveReadWriteComponentsModes[restrictColorNdx].interleaveReadWriteComponents,
2898 pipelineStateMode.pipelineStateMode, false));
2899
2900 if (!isCompressed && isDepthStencil)
2901 {
2902 // Image is depth-stencil. Add the stencil case as well.
2903 std::string stencilTestName =
2904 getFormatCaseName(format) + imageAspectTestModes[IMAGE_ASPECT_TEST_STENCIL] +
2905 testModes[testModeNdx].name +
2906 interleaveReadWriteComponentsModes[restrictColorNdx].name +
2907 pipelineStateMode.suffix;
2908 formatTests->addChild(new AttachmentFeedbackLoopLayoutSamplerTest(
2909 testCtx, pipelineConstructionType, stencilTestName.c_str(), viewType, format,
2910 outputImageSize, imageDescriptorType, 0.0f, testModes[testModeNdx].mode,
2911 IMAGE_ASPECT_TEST_STENCIL,
2912 interleaveReadWriteComponentsModes[restrictColorNdx].interleaveReadWriteComponents,
2913 pipelineStateMode.pipelineStateMode, false));
2914 }
2915 }
2916 }
2917 }
2918 }
2919
2920 viewTypeGroup->addChild(formatTests.release());
2921 imageTypeTests->addChild(viewTypeGroup.release());
2922 }
2923 imageDescriptorTypeGroup->addChild(imageTypeTests.release());
2924 samplingTypeTests->addChild(imageDescriptorTypeGroup.release());
2925 }
2926
2927 if (pipelineConstructionType == PipelineConstructionType::PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
2928 {
2929 TestCaseGroupPtr miscGroup(new tcu::TestCaseGroup(testCtx, "misc"));
2930 miscGroup->addChild(new AttachmentFeedbackLoopLayoutSamplerTest(
2931 testCtx, pipelineConstructionType, "maintenance5_color_attachment", VK_IMAGE_VIEW_TYPE_2D,
2932 VK_FORMAT_R8G8B8A8_UNORM, outputImageSize, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 0.0f, TEST_MODE_READ_ONLY,
2933 IMAGE_ASPECT_TEST_COLOR, false, PipelineStateMode::STATIC, true));
2934 miscGroup->addChild(new AttachmentFeedbackLoopLayoutSamplerTest(
2935 testCtx, pipelineConstructionType, "maintenance5_ds_attachment", VK_IMAGE_VIEW_TYPE_2D, VK_FORMAT_D16_UNORM,
2936 outputImageSize, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 0.0f, TEST_MODE_READ_ONLY, IMAGE_ASPECT_TEST_DEPTH,
2937 false, PipelineStateMode::STATIC, true));
2938 samplingTypeTests->addChild(miscGroup.release());
2939 }
2940
2941 return samplingTypeTests.release();
2942 }
2943
createAttachmentFeedbackLoopLayoutTests(tcu::TestContext & testCtx,vk::PipelineConstructionType pipelineConstructionType)2944 tcu::TestCaseGroup *createAttachmentFeedbackLoopLayoutTests(tcu::TestContext &testCtx,
2945 vk::PipelineConstructionType pipelineConstructionType)
2946 {
2947 TestCaseGroupPtr attachmentFeedbackLoopLayoutTests(
2948 new tcu::TestCaseGroup(testCtx, "attachment_feedback_loop_layout"));
2949 {
2950 attachmentFeedbackLoopLayoutTests->addChild(
2951 createAttachmentFeedbackLoopLayoutSamplerTests(testCtx, pipelineConstructionType));
2952 }
2953
2954 TestCaseGroupPtr miscGroup(new tcu::TestCaseGroup(testCtx, "misc"));
2955 {
2956 if (pipelineConstructionType == PipelineConstructionType::PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
2957 addFunctionCaseWithPrograms(miscGroup.get(), "no_color_draw", noColorAttachmentSupport,
2958 noColorAttachmentPrograms, noColorAttachmentTest);
2959 }
2960
2961 attachmentFeedbackLoopLayoutTests->addChild(miscGroup.release());
2962
2963 return attachmentFeedbackLoopLayoutTests.release();
2964 }
2965
2966 } // namespace pipeline
2967 } // namespace vkt
2968