1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2023 The Khronos Group Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Vulkan Dynamic Rendering Local Read Tests
22  *//*--------------------------------------------------------------------*/
23 
24 #include "deRandom.hpp"
25 #include "deUniquePtr.hpp"
26 
27 #include "tcuImageCompare.hpp"
28 #include "tcuRGBA.hpp"
29 #include "tcuTestLog.hpp"
30 #include "tcuTextureUtil.hpp"
31 #include "tcuVectorUtil.hpp"
32 
33 #include "vkBarrierUtil.hpp"
34 #include "vkBuilderUtil.hpp"
35 #include "vkCmdUtil.hpp"
36 #include "vktDynamicRenderingLocalReadTests.hpp"
37 #include "vkImageUtil.hpp"
38 #include "vkObjUtil.hpp"
39 #include "vkQueryUtil.hpp"
40 #include "vkRefUtil.hpp"
41 #include "vktTestGroupUtil.hpp"
42 #include "vktTestCase.hpp"
43 #include "vkTypeUtil.hpp"
44 
45 #include <iostream>
46 #include <algorithm>
47 
48 namespace vkt
49 {
50 namespace renderpass
51 {
52 namespace
53 {
54 
55 using namespace vk;
56 
57 enum class TestType
58 {
59     // Test maximum number of attachments(color + depth + stencil) readback as input
60     MAX_INPUT_ATTACHMENTS = 0,
61 
62     // Test maximum attachments remapped repeatedly
63     MAX_ATTACHMENTS_REMAPPED_REPEATEDLY,
64 
65     // Test that color attachment locations set to ATTACHMENT_UNUSED are not written, and that writes to unmapped locations are discarded
66     UNUSED_WRITEN_DISCARDED,
67 
68     // Test mapping depth + stencil to no index
69     DEPTH_STENCIL_MAPPING_TO_NO_INDEX,
70 
71     // Test mapping depth + stencil to the same index
72     DEPTH_STENCIL_MAPPING_TO_SAME_INDEX,
73 
74     // Test mapping depth + stencil so only one takes an index, the other does not
75     DEPTH_MAPPING_STENCIL_NOT,
76 
77     // Test that blend state is using unmapped indexes
78     MAPPING_NOT_AFFECTING_BLEND_STATE,
79 
80     // Test interaction with VK_EXT_color_write_enable
81     INTERACTION_WITH_COLOR_WRITE_ENABLE,
82 
83     // Test interaction with VK_EXT_extended_dynamic_state3
84     INTERACTION_WITH_EXTENDED_DYNAMIC_STATE3
85 };
86 
87 // During test creation we dont know what is the maximal number of input attachments.
88 // To be able to test maximal number of attachments we need to construct shaders for all possible
89 // numbers of input attachments. This number must also not be greater then maxColorAttachments.
90 static uint32_t inputAttachmentsPossibleValues[] = {4, 5, 6, 7, 8, 9, 10, 16, 17, 18};
91 
92 using ImageWithMemorySp  = de::SharedPtr<ImageWithMemory>;
93 using BufferWithMemorySp = de::SharedPtr<BufferWithMemory>;
94 using VkImageViewSp      = de::SharedPtr<Move<VkImageView>>;
95 
createImage(Context & context,uint32_t renderSize,VkFormat format,VkImageUsageFlags usage)96 ImageWithMemorySp createImage(Context &context, uint32_t renderSize, VkFormat format, VkImageUsageFlags usage)
97 {
98     const DeviceInterface &vk = context.getDeviceInterface();
99     VkDevice device           = context.getDevice();
100     Allocator &memAlloc       = context.getDefaultAllocator();
101     VkExtent3D extent         = makeExtent3D(renderSize, renderSize, 1u);
102 
103     const VkImageCreateInfo imageCreateInfo{
104         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
105         DE_NULL,                             // const void* pNext;
106         0u,                                  // VkImageCreateFlags flags;
107         VK_IMAGE_TYPE_2D,                    // VkImageType imageType;
108         format,                              // VkFormat format;
109         extent,                              // VkExtent3D extent;
110         1u,                                  // uint32_t mipLevels;
111         1u,                                  // uint32_t arrayLayers;
112         VK_SAMPLE_COUNT_1_BIT,               // VkSampleCountFlagBits samples;
113         VK_IMAGE_TILING_OPTIMAL,             // VkImageTiling tiling;
114         usage,                               // VkImageUsageFlags usage;
115         VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode sharingMode;
116         0u,                                  // uint32_t queueFamilyIndexCount;
117         DE_NULL,                             // const uint32_t* pQueueFamilyIndices;
118         VK_IMAGE_LAYOUT_UNDEFINED,           // VkImageLayout initialLayout;
119     };
120 
121     return ImageWithMemorySp(new ImageWithMemory(vk, device, memAlloc, imageCreateInfo, MemoryRequirement::Any));
122 }
123 
124 class BasicLocalReadTestInstance : public vkt::TestInstance
125 {
126 public:
127     BasicLocalReadTestInstance(Context &context, TestType testType);
128 
129 protected:
130     tcu::TestStatus iterate(void) override;
131 
132 private:
133     void CalculateExpectedValues(void);
134     bool UseColorWriteEnable(void) const;
135     uint32_t GetRemappedColorAttachment(uint32_t inputDrawId, uint32_t location) const;
136     uint32_t GetRemappedColorInputAttachment(uint32_t outputDrawId, uint32_t inputAttachmentIdx) const;
137 
138     const TestType m_testType;
139     const uint32_t m_renderSize;
140     VkFormat m_dsFormat;
141 
142     uint32_t m_colorAttachmentCount;
143     uint32_t m_inputDrawsCount;
144     uint32_t m_outputDrawsCount;
145     std::string m_writeFragName;
146     std::string m_readFragName;
147     std::vector<std::vector<uint32_t>> m_colorAttachmentLocations;
148     std::vector<std::vector<uint32_t>> m_colorAttachmentInputIndices;
149     uint32_t m_depthInputAttachmentIndex;
150     uint32_t m_stencilInputAttachmentIndex;
151     const VkBool32 m_colorWriteEnables[4];
152     VkBool32 m_useStencilInReadFrag;
153     std::vector<uint32_t> m_expectedValues;
154 };
155 
BasicLocalReadTestInstance(Context & context,TestType testType)156 BasicLocalReadTestInstance::BasicLocalReadTestInstance(Context &context, TestType testType)
157     : vkt::TestInstance(context)
158     , m_testType(testType)
159     , m_renderSize(16)
160     , m_dsFormat(VK_FORMAT_D24_UNORM_S8_UINT)
161     , m_colorAttachmentCount(4)
162     , m_inputDrawsCount(1)
163     , m_outputDrawsCount(1)
164     , m_writeFragName("frag0")
165     , m_readFragName("frag1")
166     , m_colorAttachmentLocations{{0, 1, 2, 3}}
167     , m_colorAttachmentInputIndices{{0, 1, 2, 3}}
168     , m_depthInputAttachmentIndex(4)
169     , m_stencilInputAttachmentIndex(5)
170     , m_colorWriteEnables{0, 1, 0, 1}
171     , m_useStencilInReadFrag(true)
172     , m_expectedValues{0}
173 {
174     const InstanceInterface &vki                = m_context.getInstanceInterface();
175     VkPhysicalDevice physicalDevice             = m_context.getPhysicalDevice();
176     const VkPhysicalDeviceProperties properties = getPhysicalDeviceProperties(vki, physicalDevice);
177 
178     // pick depth stencil format (one of those two has to be supported)
179     VkImageFormatProperties imageFormatProperties;
180     if (vki.getPhysicalDeviceImageFormatProperties(
181             physicalDevice, m_dsFormat, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
182             VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT, 0,
183             &imageFormatProperties))
184         m_dsFormat = VK_FORMAT_D32_SFLOAT_S8_UINT;
185 
186     // setup test configuration - all test cases use same test instance code but with diferent parameters
187     switch (m_testType)
188     {
189     case TestType::MAX_INPUT_ATTACHMENTS:
190     {
191         m_colorAttachmentCount = deMinu32(properties.limits.maxColorAttachments,
192                                           properties.limits.maxPerStageDescriptorInputAttachments - 2u);
193 
194         // if this assert is trigered then shader for number m_colorAttachmentCount+2 was not prepared;
195         // to fix this just add value of m_colorAttachmentCount+2 to the inputAttachmentsPossibleValues array on top of this file
196         DE_ASSERT(std::find(std::begin(inputAttachmentsPossibleValues), std::end(inputAttachmentsPossibleValues),
197                             m_colorAttachmentCount + 2) != std::end(inputAttachmentsPossibleValues));
198 
199         m_writeFragName += "_" + std::to_string(m_colorAttachmentCount);
200         m_readFragName +=
201             "_" + std::to_string(m_colorAttachmentCount + 2u); // +2 because depth and stencil are read too
202         m_depthInputAttachmentIndex   = m_colorAttachmentCount;
203         m_stencilInputAttachmentIndex = m_colorAttachmentCount + 1;
204 
205         m_colorAttachmentLocations[0].resize(m_colorAttachmentCount);
206         m_colorAttachmentInputIndices[0].resize(m_colorAttachmentCount);
207         for (uint32_t attIndex = 0; attIndex < m_colorAttachmentCount; ++attIndex)
208         {
209             m_colorAttachmentLocations[0][attIndex]    = attIndex;
210             m_colorAttachmentInputIndices[0][attIndex] = attIndex;
211         }
212         break;
213     }
214     case TestType::MAX_ATTACHMENTS_REMAPPED_REPEATEDLY:
215     {
216         m_colorAttachmentCount = deMinu32(properties.limits.maxColorAttachments,
217                                           properties.limits.maxPerStageDescriptorInputAttachments - 2u);
218         m_inputDrawsCount      = m_colorAttachmentCount / 2u;
219         m_colorAttachmentCount = m_inputDrawsCount * 2u;
220         m_outputDrawsCount     = 3;
221         m_readFragName +=
222             "_" + std::to_string(m_colorAttachmentCount + 2u); // +2 because depth and stencil are read too
223         m_depthInputAttachmentIndex   = m_colorAttachmentCount;
224         m_stencilInputAttachmentIndex = m_colorAttachmentCount + 1;
225 
226         // each input draw uses just two color attachments; each time its different pair that is always mapped to location 0 and 1
227         m_colorAttachmentLocations.clear();
228         m_colorAttachmentLocations.resize(m_inputDrawsCount,
229                                           std::vector<uint32_t>(m_colorAttachmentCount, VK_ATTACHMENT_UNUSED));
230         for (uint32_t inputDraw = 0; inputDraw < m_inputDrawsCount; ++inputDraw)
231         {
232             auto &colorAttachmentLocations       = m_colorAttachmentLocations[inputDraw];
233             uint32_t index                       = 2u * inputDraw;
234             colorAttachmentLocations[index]      = 0u;
235             colorAttachmentLocations[index + 1u] = 1u;
236         }
237 
238         // allocate space for all different remappings
239         m_colorAttachmentInputIndices.resize(m_outputDrawsCount);
240         for (auto &inputIndices : m_colorAttachmentInputIndices)
241             inputIndices.resize(m_colorAttachmentCount);
242 
243         // each output draw will use all input attachments but remapped differently
244         // first remapping: reversed order, from greatest index to smallest
245         // second remapping: alternately takes the smallest not used index and then the largest not used index
246         // third remapping: same order as index, from smallest index to greatest
247         for (uint32_t attIndex = 0; attIndex < m_colorAttachmentCount; ++attIndex)
248         {
249             m_colorAttachmentInputIndices[0][attIndex] = m_colorAttachmentCount - 1 - attIndex;
250             m_colorAttachmentInputIndices[1][attIndex] =
251                 (attIndex % 2) ? (m_colorAttachmentCount - 1 - attIndex / 2u) : (attIndex / 2u);
252             m_colorAttachmentInputIndices[2][attIndex] = attIndex;
253         }
254         break;
255     }
256     case TestType::UNUSED_WRITEN_DISCARDED:
257     {
258         m_useStencilInReadFrag           = true;
259         m_colorAttachmentCount           = 4;
260         m_colorAttachmentLocations[0][0] = VK_ATTACHMENT_UNUSED;
261         m_colorAttachmentLocations[0][2] = VK_ATTACHMENT_UNUSED;
262         break;
263     }
264     case TestType::DEPTH_STENCIL_MAPPING_TO_NO_INDEX:
265     {
266         m_useStencilInReadFrag        = true;
267         m_colorAttachmentCount        = 2;
268         m_depthInputAttachmentIndex   = VK_ATTACHMENT_UNUSED;
269         m_stencilInputAttachmentIndex = VK_ATTACHMENT_UNUSED;
270         break;
271     }
272     case TestType::DEPTH_STENCIL_MAPPING_TO_SAME_INDEX:
273     {
274         m_useStencilInReadFrag        = true;
275         m_colorAttachmentCount        = 2;
276         m_depthInputAttachmentIndex   = 2;
277         m_stencilInputAttachmentIndex = 2;
278         break;
279     }
280     case TestType::DEPTH_MAPPING_STENCIL_NOT:
281     {
282         m_useStencilInReadFrag        = false;
283         m_colorAttachmentCount        = 4;
284         m_depthInputAttachmentIndex   = 4;
285         m_stencilInputAttachmentIndex = VK_ATTACHMENT_UNUSED;
286         break;
287     }
288     case TestType::INTERACTION_WITH_COLOR_WRITE_ENABLE:
289     {
290         m_useStencilInReadFrag        = false;
291         m_colorAttachmentCount        = 4;
292         m_colorAttachmentLocations    = {{0, 3, 1, 2}};
293         m_depthInputAttachmentIndex   = 4;
294         m_stencilInputAttachmentIndex = VK_ATTACHMENT_UNUSED;
295         break;
296     }
297     case TestType::INTERACTION_WITH_EXTENDED_DYNAMIC_STATE3:
298     {
299         m_useStencilInReadFrag        = false;
300         m_colorAttachmentCount        = 4;
301         m_colorAttachmentLocations    = {{0, 3, 1, 2}};
302         m_depthInputAttachmentIndex   = 4;
303         m_stencilInputAttachmentIndex = VK_ATTACHMENT_UNUSED;
304         break;
305     }
306     default:
307         DE_ASSERT(false);
308         break;
309     }
310 
311     CalculateExpectedValues();
312 }
313 
GetRemappedColorAttachment(uint32_t inputDrawId,uint32_t location) const314 uint32_t BasicLocalReadTestInstance::GetRemappedColorAttachment(uint32_t inputDrawId, uint32_t location) const
315 {
316     uint32_t attIndexRemaped = VK_ATTACHMENT_UNUSED;
317 
318     // Find the remapped attachment index of a output color with decorator location = colorIdx in generateWriteFragSource
319     for (uint32_t i = 0; i < m_colorAttachmentCount; i++)
320     {
321         if (location == m_colorAttachmentLocations[inputDrawId][i])
322         {
323             attIndexRemaped = i;
324             break;
325         }
326     }
327 
328     return attIndexRemaped;
329 }
330 
GetRemappedColorInputAttachment(uint32_t outputDrawId,uint32_t inputAttachmentIdx) const331 uint32_t BasicLocalReadTestInstance::GetRemappedColorInputAttachment(uint32_t outputDrawId,
332                                                                      uint32_t inputAttachmentIdx) const
333 {
334     // perform same operation as in frag1_* shader to calculate final expected value
335     uint32_t attIndexRemaped = VK_ATTACHMENT_UNUSED;
336 
337     for (uint32_t i = 0; i < m_colorAttachmentCount; i++)
338     {
339         if (inputAttachmentIdx == m_colorAttachmentInputIndices[outputDrawId][i])
340         {
341             attIndexRemaped = i;
342             break;
343         }
344     }
345 
346     DE_ASSERT(attIndexRemaped != VK_ATTACHMENT_UNUSED);
347 
348     return attIndexRemaped;
349 }
350 
CalculateExpectedValues()351 void BasicLocalReadTestInstance::CalculateExpectedValues()
352 {
353     // generate same valueas for each attachment as in frag0_* shader
354     std::vector<uint32_t> valuesPerColorAttachment(m_colorAttachmentCount, 0);
355 
356     for (uint32_t inputDraw = 0; inputDraw < m_inputDrawsCount; ++inputDraw)
357     {
358         for (uint32_t colorIdx = 0; colorIdx < m_colorAttachmentCount / m_inputDrawsCount; colorIdx++)
359         {
360             uint32_t outColor        = 0;
361             uint32_t attIndexRemaped = GetRemappedColorAttachment(inputDraw, colorIdx);
362 
363             // Calculate the shader ouput in generateWriteFragSource
364             if ((UseColorWriteEnable() == false) || (m_colorWriteEnables[attIndexRemaped] == 1))
365             {
366                 outColor = (2u * inputDraw + colorIdx + 1u) * (2u * inputDraw + colorIdx + 1u);
367             }
368 
369             // Write color output to the remapped attachment
370             if (attIndexRemaped != VK_ATTACHMENT_UNUSED)
371             {
372                 valuesPerColorAttachment[attIndexRemaped] = outColor;
373             }
374         }
375     }
376 
377     // calculate expected values for all three output draws, same as it will be done in frag1_* shader
378     m_expectedValues.resize(m_outputDrawsCount);
379 
380     for (uint32_t outputDraw = 0; outputDraw < m_outputDrawsCount; ++outputDraw)
381     {
382         // Depth read is 0.6 and stencil read is 1. Depth read is already enabled, but stencil read depends on test type.
383         const float depthRead      = 0.6f;
384         const uint32_t stencilRead = 1;
385 
386         if (m_testType == TestType::DEPTH_STENCIL_MAPPING_TO_NO_INDEX)
387         {
388             // Depth read and stencil read are both enabled
389             m_expectedValues[outputDraw] = static_cast<uint32_t>(depthRead * 1000) + stencilRead * 100;
390         }
391         else if (m_testType == TestType::DEPTH_STENCIL_MAPPING_TO_SAME_INDEX)
392         {
393             // Depth read and stencil read are both enabled
394             m_expectedValues[outputDraw] = static_cast<uint32_t>(depthRead * 1000) + stencilRead;
395         }
396         else
397         {
398             m_expectedValues[outputDraw] =
399                 static_cast<uint32_t>(depthRead * 1000) + ((m_useStencilInReadFrag) ? (stencilRead * 1000) : 0);
400         }
401 
402         // each output draw uses all attachments but remaped differently
403         for (uint32_t attIndex = 0; attIndex < m_colorAttachmentCount; ++attIndex)
404         {
405             uint32_t attIndexRemaped = GetRemappedColorInputAttachment(outputDraw, attIndex);
406 
407             if (m_testType == TestType::DEPTH_STENCIL_MAPPING_TO_NO_INDEX)
408             {
409                 // Accumulate inColor_i, in which inColor_i is the color attachment with location = i in shader
410                 m_expectedValues[outputDraw] += valuesPerColorAttachment[attIndexRemaped];
411             }
412             else if (m_testType == TestType::DEPTH_STENCIL_MAPPING_TO_SAME_INDEX)
413             {
414                 // No color is read
415                 break;
416             }
417             else
418             {
419                 // Accumulate i * inColor_i, in which inColor_i is the color attachment with location = i in shader
420                 m_expectedValues[outputDraw] += (attIndex + 1u) * valuesPerColorAttachment[attIndexRemaped];
421             }
422         }
423     }
424 }
425 
UseColorWriteEnable() const426 bool BasicLocalReadTestInstance::UseColorWriteEnable() const
427 {
428     return (m_testType == TestType::INTERACTION_WITH_COLOR_WRITE_ENABLE) ? true : false;
429 }
430 
iterate(void)431 tcu::TestStatus BasicLocalReadTestInstance::iterate(void)
432 {
433     const DeviceInterface &vk              = m_context.getDeviceInterface();
434     const VkDevice device                  = m_context.getDevice();
435     Allocator &memAlloc                    = m_context.getDefaultAllocator();
436     VkQueue queue                          = m_context.getUniversalQueue();
437     const uint32_t queueFamilyIndex        = m_context.getUniversalQueueFamilyIndex();
438     const VkImageSubresourceRange colorSRR = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
439     const VkImageSubresourceRange dSRR     = makeImageSubresourceRange(VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 1u, 0u, 1u);
440     const VkImageSubresourceRange sSRR     = makeImageSubresourceRange(VK_IMAGE_ASPECT_STENCIL_BIT, 0u, 1u, 0u, 1u);
441     const VkImageSubresourceRange dsSRR = makeImageSubresourceRange(dSRR.aspectMask | sSRR.aspectMask, 0u, 1u, 0u, 1u);
442     const std::vector<VkViewport> viewports{makeViewport(m_renderSize, m_renderSize)};
443     const std::vector<VkRect2D> scissors{makeRect2D(m_renderSize, m_renderSize)};
444     const bool useColorWriteEnable = UseColorWriteEnable();
445     const bool useUseExtendedDynamicState3(m_testType == TestType::INTERACTION_WITH_EXTENDED_DYNAMIC_STATE3);
446 
447     // define few structures that will be modified and reused in multiple places
448     VkImageMemoryBarrier colorImageBarrier =
449         makeImageMemoryBarrier(0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
450                                VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ_KHR, 0, colorSRR);
451     VkImageMemoryBarrier dsImageBarrier =
452         makeImageMemoryBarrier(0, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
453                                VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ_KHR, 0, dsSRR);
454     VkRenderingAttachmentInfo depthStencilAttachment{
455         VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO, // VkStructureType sType;
456         DE_NULL,                                     // const void* pNext;
457         DE_NULL,                                     // VkImageView imageView;
458         VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ_KHR,    // VkImageLayout imageLayout;
459         VK_RESOLVE_MODE_NONE,                        // VkResolveModeFlagBits resolveMode;
460         DE_NULL,                                     // VkImageView resolveImageView;
461         VK_IMAGE_LAYOUT_UNDEFINED,                   // VkImageLayout resolveImageLayout;
462         VK_ATTACHMENT_LOAD_OP_CLEAR,                 // VkAttachmentLoadOp loadOp;
463         VK_ATTACHMENT_STORE_OP_STORE,                // VkAttachmentStoreOp storeOp;
464         makeClearValueColor(tcu::Vec4(0.0f))         // VkClearValue clearValue;
465     };
466     VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT |
467                                    VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
468     VkDescriptorImageInfo depthImageDescriptor(
469         makeDescriptorImageInfo(DE_NULL, DE_NULL, VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ_KHR));
470     VkDescriptorImageInfo stencilImageDescriptor(depthImageDescriptor);
471 
472     // construct required containers
473     std::vector<ImageWithMemorySp> images(m_colorAttachmentCount + 1,
474                                           ImageWithMemorySp()); // +1 for depth+stencil image
475     std::vector<VkImageViewSp> imageViews(m_colorAttachmentCount + 3,
476                                           VkImageViewSp()); // +3 for separate depth and stencil and depth+stencil
477     std::vector<VkFormat> colorImageFormats(m_colorAttachmentCount, VK_FORMAT_R32_UINT);
478     std::vector<VkImageMemoryBarrier> colorImageBarriers(m_colorAttachmentCount, colorImageBarrier);
479     std::vector<VkRenderingAttachmentInfo> colorAttachments(m_colorAttachmentCount, depthStencilAttachment);
480     std::vector<VkDescriptorImageInfo> colorImageDescriptors(m_colorAttachmentCount, depthImageDescriptor);
481     std::vector<BufferWithMemorySp> outputBuffers(m_outputDrawsCount, BufferWithMemorySp());
482     std::vector<Move<VkPipeline>> writeGraphicsPipelines(m_inputDrawsCount);
483     std::vector<Move<VkPipeline>> readGraphicsPipelines(m_outputDrawsCount);
484 
485     // create images and image views for color attachments and use same loop to fill other needed containers
486     for (uint32_t attIndex = 0; attIndex < m_colorAttachmentCount; ++attIndex)
487     {
488         images[attIndex]     = createImage(m_context, m_renderSize, colorImageFormats[attIndex], imageUsage);
489         imageViews[attIndex] = VkImageViewSp(new vk::Move<VkImageView>(makeImageView(
490             vk, device, **images[attIndex], VK_IMAGE_VIEW_TYPE_2D, colorImageFormats[attIndex], colorSRR)));
491 
492         colorImageBarriers[attIndex].image        = **images[attIndex];
493         colorAttachments[attIndex].imageView      = **imageViews[attIndex];
494         colorImageDescriptors[attIndex].imageView = **imageViews[attIndex];
495     }
496 
497     // create image and image views for depth/stencil attachments
498     uint32_t depthIndex              = m_colorAttachmentCount;
499     images[depthIndex]               = createImage(m_context, m_renderSize, m_dsFormat,
500                                                    VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT |
501                                                        VK_IMAGE_USAGE_TRANSFER_DST_BIT);
502     imageViews[depthIndex]           = VkImageViewSp(new vk::Move<VkImageView>(
503         makeImageView(vk, device, **images[depthIndex], VK_IMAGE_VIEW_TYPE_2D, m_dsFormat, dSRR)));
504     imageViews[depthIndex + 1]       = VkImageViewSp(new vk::Move<VkImageView>(
505         makeImageView(vk, device, **images[depthIndex], VK_IMAGE_VIEW_TYPE_2D, m_dsFormat, sSRR)));
506     imageViews[depthIndex + 2]       = VkImageViewSp(new vk::Move<VkImageView>(
507         makeImageView(vk, device, **images[depthIndex], VK_IMAGE_VIEW_TYPE_2D, m_dsFormat, dsSRR)));
508     dsImageBarrier.image             = **images[depthIndex];
509     depthImageDescriptor.imageView   = **imageViews[depthIndex];
510     stencilImageDescriptor.imageView = **imageViews[depthIndex + 1];
511     depthStencilAttachment.imageView = **imageViews[depthIndex + 2];
512 
513     // define buffers for output
514     const VkDeviceSize outputBufferSize = static_cast<VkDeviceSize>(m_renderSize * m_renderSize * sizeof(uint32_t));
515     const VkBufferCreateInfo bufferCreateInfo =
516         makeBufferCreateInfo(outputBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
517     for (uint32_t buffIndex = 0; buffIndex < m_outputDrawsCount; ++buffIndex)
518         outputBuffers[buffIndex] = BufferWithMemorySp(
519             new BufferWithMemory(vk, device, memAlloc, bufferCreateInfo, MemoryRequirement::HostVisible));
520 
521     // create descriptors, they are needed just for read pipelines (usually there is just one read pipeline)
522     Move<VkDescriptorPool> descriptorPool =
523         DescriptorPoolBuilder()
524             .addType(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, (m_colorAttachmentCount + 2u) * m_outputDrawsCount)
525             .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, m_outputDrawsCount)
526             .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 2u * m_outputDrawsCount);
527 
528     // first descriptor set contains all input attachments
529     DescriptorSetLayoutBuilder descriptorSetLayoutABuilder;
530     for (uint32_t attIndex = 0; attIndex < m_colorAttachmentCount + 2; ++attIndex)
531         descriptorSetLayoutABuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, VK_SHADER_STAGE_FRAGMENT_BIT);
532     Move<VkDescriptorSetLayout> descriptorSetLayoutA = descriptorSetLayoutABuilder.build(vk, device);
533 
534     // second and following descriptor sets contain just single output buffer each
535     Move<VkDescriptorSetLayout> descriptorSetLayoutB =
536         DescriptorSetLayoutBuilder()
537             .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT)
538             .build(vk, device);
539 
540     std::vector<Move<VkDescriptorSet>> bufferDescriptorSets(m_outputDrawsCount);
541     std::vector<Move<VkDescriptorSet>> inputAttachmentsDescriptorSets(m_outputDrawsCount);
542     for (uint32_t i = 0; i < m_outputDrawsCount; ++i)
543     {
544         inputAttachmentsDescriptorSets[i] = makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayoutA);
545         bufferDescriptorSets[i]           = makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayoutB);
546     }
547 
548     // set descriptor sets for all input attachments
549     using DSLocation = DescriptorSetUpdateBuilder::Location;
550     DescriptorSetUpdateBuilder descriptorSetUpdateBuilder;
551     for (uint32_t i = 0; i < m_outputDrawsCount; ++i)
552     {
553         // content of the descriptor set with input attachment bindings must be consistent with the remapping
554         for (uint32_t attIndex = 0; attIndex < m_colorAttachmentCount; ++attIndex)
555         {
556             uint32_t remapedIndex = GetRemappedColorInputAttachment(i, attIndex);
557 
558             descriptorSetUpdateBuilder.writeSingle(*inputAttachmentsDescriptorSets[i], DSLocation::binding(attIndex),
559                                                    VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
560                                                    &colorImageDescriptors[remapedIndex]);
561         }
562         descriptorSetUpdateBuilder.writeSingle(*inputAttachmentsDescriptorSets[i],
563                                                DSLocation::binding(m_colorAttachmentCount),
564                                                VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, &depthImageDescriptor);
565         descriptorSetUpdateBuilder.writeSingle(*inputAttachmentsDescriptorSets[i],
566                                                DSLocation::binding(m_colorAttachmentCount + 1),
567                                                VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, &stencilImageDescriptor);
568     }
569 
570     // set descriptor sets for all output buffers
571     VkDescriptorBufferInfo bufferInfo = makeDescriptorBufferInfo(DE_NULL, 0u, VK_WHOLE_SIZE);
572     for (uint32_t buffIndex = 0; buffIndex < m_outputDrawsCount; ++buffIndex)
573     {
574         bufferInfo.buffer = **outputBuffers[buffIndex];
575         descriptorSetUpdateBuilder.writeSingle(*bufferDescriptorSets[buffIndex], DSLocation::binding(0),
576                                                VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &bufferInfo);
577     }
578 
579     // update descriptor sets
580     descriptorSetUpdateBuilder.update(vk, device);
581 
582     // create components for pipelines
583     const VkPushConstantRange pushConstantRange             = {VK_SHADER_STAGE_FRAGMENT_BIT, 0, 4};
584     std::vector<VkDescriptorSetLayout> descriptorSetLayouts = {*descriptorSetLayoutA, *descriptorSetLayoutB};
585     Move<VkPipelineLayout> writePipelineLayout = makePipelineLayout(vk, device, 0, DE_NULL, 1u, &pushConstantRange);
586     Move<VkPipelineLayout> readPipelineLayout  = makePipelineLayout(vk, device, descriptorSetLayouts);
587     Move<VkShaderModule> vertShaderModule =
588         createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0);
589     Move<VkShaderModule> writeFragShaderModule =
590         createShaderModule(vk, device, m_context.getBinaryCollection().get(m_writeFragName), 0);
591     Move<VkShaderModule> readFragShaderModule =
592         createShaderModule(vk, device, m_context.getBinaryCollection().get(m_readFragName), 0);
593 
594     // define empty VertexInputState, full screen quad will be generated in vertex shader
595     const VkPipelineVertexInputStateCreateInfo vertexInputState = initVulkanStructure();
596 
597     // define ColorBlendState so that we can write to multiple color attachments
598     const VkPipelineColorBlendAttachmentState colorBlendAttachmentState{0,
599                                                                         VK_BLEND_FACTOR_ZERO,
600                                                                         VK_BLEND_FACTOR_ZERO,
601                                                                         VK_BLEND_OP_ADD,
602                                                                         VK_BLEND_FACTOR_ZERO,
603                                                                         VK_BLEND_FACTOR_ZERO,
604                                                                         VK_BLEND_OP_ADD,
605                                                                         0xf};
606     std::vector<VkPipelineColorBlendAttachmentState> colorBlendAttachmentStates(m_colorAttachmentCount,
607                                                                                 colorBlendAttachmentState);
608     VkPipelineColorBlendStateCreateInfo colorBlendStateCreateInfo = initVulkanStructure();
609     colorBlendStateCreateInfo.attachmentCount                     = (uint32_t)colorBlendAttachmentStates.size();
610     colorBlendStateCreateInfo.pAttachments                        = colorBlendAttachmentStates.data();
611 
612     // define MultisampleState, it is only needed to test if CmdSetRasterizationSamplesEXT does not affect local_read remappings
613     VkPipelineMultisampleStateCreateInfo multisampleStateCreateInfo = initVulkanStructure();
614     multisampleStateCreateInfo.rasterizationSamples =
615         useUseExtendedDynamicState3 ? VK_SAMPLE_COUNT_2_BIT : VK_SAMPLE_COUNT_1_BIT;
616     multisampleStateCreateInfo.minSampleShading = 1.0f;
617 
618     // define DepthStencilState so that we can write to depth and stencil attachments
619     const VkStencilOpState stencilOpState{
620         VK_STENCIL_OP_KEEP,                // VkStencilOp                                failOp
621         VK_STENCIL_OP_INCREMENT_AND_CLAMP, // VkStencilOp                                passOp
622         VK_STENCIL_OP_KEEP,                // VkStencilOp                                depthFailOp
623         VK_COMPARE_OP_ALWAYS,              // VkCompareOp                                compareOp
624         0xffu,                             // uint32_t                                    compareMask
625         0xffu,                             // uint32_t                                    writeMask
626         0                                  // uint32_t                                    reference
627     };
628     VkPipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo{
629         VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType                            sType
630         DE_NULL,                                                    // const void*                                pNext
631         0u,                                                         // VkPipelineDepthStencilStateCreateFlags    flags
632         VK_TRUE,               // VkBool32                                    depthTestEnable
633         VK_TRUE,               // VkBool32                                    depthWriteEnable
634         VK_COMPARE_OP_GREATER, // VkCompareOp                                depthCompareOp
635         VK_FALSE,              // VkBool32                                    depthBoundsTestEnable
636         VK_TRUE,               // VkBool32                                    stencilTestEnable
637         stencilOpState,        // VkStencilOpState                            front
638         stencilOpState,        // VkStencilOpState                            back
639         0.0f,                  // float                                    minDepthBounds
640         1.0f,                  // float                                    maxDepthBounds
641     };
642 
643     VkDynamicState dynamicState = VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT;
644     if (useUseExtendedDynamicState3)
645         dynamicState = VK_DYNAMIC_STATE_RASTERIZATION_SAMPLES_EXT;
646     VkPipelineDynamicStateCreateInfo dynamicStateCreateInfo{
647         VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType                        sType
648         DE_NULL,                                              // const void*                            pNext
649         0u,                                                   // VkPipelineDynamicStateCreateFlags    flags
650         1u,           // uint32_t                                dynamicStateCount
651         &dynamicState // const VkDynamicState*                pDynamicStates
652     };
653     VkPipelineDynamicStateCreateInfo *writeDynamicStateCreateInfo = nullptr;
654     if (useColorWriteEnable || useUseExtendedDynamicState3)
655         writeDynamicStateCreateInfo = &dynamicStateCreateInfo;
656 
657     VkRenderingAttachmentLocationInfoKHR renderingAttachmentLocationInfo{
658         VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_LOCATION_INFO_KHR, DE_NULL, m_colorAttachmentCount, DE_NULL};
659     VkRenderingInputAttachmentIndexInfoKHR renderingInputAttachmentIndexInfo{
660         VK_STRUCTURE_TYPE_RENDERING_INPUT_ATTACHMENT_INDEX_INFO_KHR,
661         DE_NULL,
662         m_colorAttachmentCount,
663         DE_NULL,
664         &m_depthInputAttachmentIndex,
665         &m_stencilInputAttachmentIndex};
666     VkPipelineRenderingCreateInfo renderingCreateInfo{VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
667                                                       &renderingAttachmentLocationInfo,
668                                                       0u,
669                                                       (uint32_t)colorImageFormats.size(),
670                                                       colorImageFormats.data(),
671                                                       m_dsFormat,
672                                                       m_dsFormat};
673 
674     // create write pipelines that writes to color attachments
675     for (uint32_t pipelineIndex = 0; pipelineIndex < m_inputDrawsCount; ++pipelineIndex)
676     {
677         renderingAttachmentLocationInfo.pColorAttachmentLocations = m_colorAttachmentLocations[pipelineIndex].data();
678         writeGraphicsPipelines[pipelineIndex]                     = makeGraphicsPipeline(
679             vk, device, *writePipelineLayout, *vertShaderModule, DE_NULL, DE_NULL, DE_NULL, *writeFragShaderModule,
680             DE_NULL, viewports, scissors, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 0, 0, &vertexInputState, DE_NULL,
681             &multisampleStateCreateInfo, &depthStencilStateCreateInfo, &colorBlendStateCreateInfo,
682             writeDynamicStateCreateInfo, &renderingCreateInfo);
683 
684         // writte to depth and stencil only in first pipeline
685         depthStencilStateCreateInfo.depthTestEnable   = false;
686         depthStencilStateCreateInfo.stencilTestEnable = false;
687     }
688 
689     // read pipelines need input attachments remaping
690     renderingCreateInfo.pNext = &renderingInputAttachmentIndexInfo;
691 
692     // read pipelines don't write to the color attachments
693     for (auto &cb : colorBlendAttachmentStates)
694         cb.colorWriteMask = 0;
695 
696     // Per spec, if either of pDepthInputAttachmentIndex or pStencilInputAttachmentIndex are set to NULL it means that these are only accessible in the shader
697     // if the shader does not associate these input attachments with an InputAttachmentIndex.
698     if (m_testType == TestType::DEPTH_STENCIL_MAPPING_TO_NO_INDEX)
699     {
700         renderingInputAttachmentIndexInfo.pDepthInputAttachmentIndex   = NULL;
701         renderingInputAttachmentIndexInfo.pStencilInputAttachmentIndex = NULL;
702     }
703 
704     for (uint32_t pipelineIndex = 0; pipelineIndex < m_outputDrawsCount; ++pipelineIndex)
705     {
706         renderingInputAttachmentIndexInfo.pColorAttachmentInputIndices =
707             m_colorAttachmentInputIndices[pipelineIndex].data();
708         readGraphicsPipelines[pipelineIndex] = makeGraphicsPipeline(
709             vk, device, *readPipelineLayout, *vertShaderModule, DE_NULL, DE_NULL, DE_NULL, *readFragShaderModule,
710             DE_NULL, viewports, scissors, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 1, 0, &vertexInputState, DE_NULL,
711             DE_NULL, DE_NULL, &colorBlendStateCreateInfo, DE_NULL, &renderingCreateInfo);
712     }
713 
714     Move<VkCommandPool> commandPool =
715         createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
716     Move<VkCommandBuffer> commandBuffer =
717         allocateCommandBuffer(vk, device, *commandPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY);
718     VkCommandBuffer cmdBuffer = *commandBuffer;
719 
720     VkRenderingInfo renderingInfo{
721         VK_STRUCTURE_TYPE_RENDERING_INFO,
722         DE_NULL,
723         0u,                                // VkRenderingFlags                        flags
724         scissors[0],                       // VkRect2D                                renderArea
725         1u,                                // uint32_t                                layerCount
726         0u,                                // uint32_t                                viewMask
727         (uint32_t)colorAttachments.size(), // uint32_t                                colorAttachmentCount
728         colorAttachments.data(),           // const VkRenderingAttachmentInfo*        pColorAttachments
729         &depthStencilAttachment,           // const VkRenderingAttachmentInfo*        pDepthAttachment
730         &depthStencilAttachment            // const VkRenderingAttachmentInfo*        pStencilAttachment
731     };
732 
733     // record commands
734     beginCommandBuffer(vk, cmdBuffer);
735 
736     // transition all images to proper layouts
737     vk.cmdPipelineBarrier(cmdBuffer, 0, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 0, DE_NULL, 0, DE_NULL,
738                           (uint32_t)colorImageBarriers.size(), colorImageBarriers.data());
739     vk.cmdPipelineBarrier(cmdBuffer, 0, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, 0, 0, DE_NULL, 0, DE_NULL, 1u,
740                           &dsImageBarrier);
741 
742     vk.cmdBeginRendering(cmdBuffer, &renderingInfo);
743 
744     // draw using write pipelines
745     for (uint32_t pipelineIndex = 0; pipelineIndex < m_inputDrawsCount; ++pipelineIndex)
746     {
747         renderingAttachmentLocationInfo.pColorAttachmentLocations = m_colorAttachmentLocations[pipelineIndex].data();
748 
749         vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *writeGraphicsPipelines[pipelineIndex]);
750         vk.cmdPushConstants(cmdBuffer, *writePipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0, 4, &pipelineIndex);
751         vk.cmdSetRenderingAttachmentLocationsKHR(cmdBuffer, &renderingAttachmentLocationInfo);
752 
753         if (useColorWriteEnable)
754             vk.cmdSetColorWriteEnableEXT(cmdBuffer, 4u, m_colorWriteEnables);
755         if (useUseExtendedDynamicState3)
756             vk.cmdSetRasterizationSamplesEXT(cmdBuffer, VK_SAMPLE_COUNT_1_BIT);
757 
758         vk.cmdDraw(cmdBuffer, 4u, 1u, 0u, 0u);
759     }
760 
761     // reuse existing barrier structures to finish rendering before next subpass
762     dsImageBarrier.oldLayout     = VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ_KHR;
763     dsImageBarrier.newLayout     = VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ_KHR;
764     dsImageBarrier.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
765     dsImageBarrier.dstAccessMask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
766     for (auto &barrier : colorImageBarriers)
767     {
768         barrier.oldLayout     = VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ_KHR;
769         barrier.newLayout     = VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ_KHR;
770         barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
771         barrier.dstAccessMask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
772     }
773     vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
774                           VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, DE_NULL, 0, DE_NULL,
775                           (uint32_t)colorImageBarriers.size(), colorImageBarriers.data());
776     vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
777                           VK_DEPENDENCY_BY_REGION_BIT, 0, DE_NULL, 0, DE_NULL, 1u, &dsImageBarrier);
778 
779     // draw using read pipelines
780     for (uint32_t pipelineIndex = 0; pipelineIndex < m_outputDrawsCount; ++pipelineIndex)
781     {
782         VkDescriptorSet descriptorSets[] = {*inputAttachmentsDescriptorSets[pipelineIndex],
783                                             *bufferDescriptorSets[pipelineIndex]};
784         renderingInputAttachmentIndexInfo.pColorAttachmentInputIndices =
785             m_colorAttachmentInputIndices[pipelineIndex].data();
786 
787         vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *readGraphicsPipelines[pipelineIndex]);
788         vk.cmdSetRenderingInputAttachmentIndicesKHR(cmdBuffer, &renderingInputAttachmentIndexInfo);
789         vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *readPipelineLayout, 0u, 2u,
790                                  descriptorSets, 0u, DE_NULL);
791         vk.cmdDraw(cmdBuffer, 4u, 1u, 0u, 0u);
792     }
793 
794     vk.cmdEndRendering(cmdBuffer);
795 
796     endCommandBuffer(vk, cmdBuffer);
797     submitCommandsAndWait(vk, device, queue, cmdBuffer);
798 
799     // verify all output buffers
800     bool allOk = true;
801     auto &log  = m_context.getTestContext().getLog();
802     DE_ASSERT(m_expectedValues.size() == m_outputDrawsCount);
803     for (uint32_t buffIndex = 0; buffIndex < m_outputDrawsCount; ++buffIndex)
804     {
805         // get output buffer
806         const Allocation &bufferAllocation = outputBuffers[buffIndex]->getAllocation();
807         invalidateAlloc(vk, device, bufferAllocation);
808 
809         // validate result
810         const uint32_t *bufferPtr = static_cast<uint32_t *>(bufferAllocation.getHostPtr());
811         const uint32_t expected   = m_expectedValues[buffIndex];
812         for (uint32_t i = 0; i < m_renderSize * m_renderSize; ++i)
813         {
814             if (bufferPtr[i] != expected)
815             {
816                 log << tcu::TestLog::Message << "Result for buffer " << buffIndex << ": expected " << expected
817                     << " got " << bufferPtr[i] << " at index " << i << tcu::TestLog::EndMessage;
818                 allOk = false;
819                 break;
820             }
821         }
822     }
823 
824     if (allOk)
825         return tcu::TestStatus::pass("Pass");
826 
827     const VkBufferCreateInfo attBufferCreateInfo =
828         makeBufferCreateInfo(outputBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
829     BufferWithMemorySp attBuffer(
830         new BufferWithMemory(vk, device, memAlloc, attBufferCreateInfo, MemoryRequirement::HostVisible));
831     vk::VkBufferImageCopy region{0, 0, 0, {1, 0, 0, 1}, {0, 0, 0}, {1, 1, 1}};
832     auto &barrier = colorImageBarriers[0];
833 
834     // reuse first barrier structure
835     barrier.oldLayout     = VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ_KHR;
836     barrier.newLayout     = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
837     barrier.srcAccessMask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
838     barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
839 
840     // log content of each color attachment
841     for (uint32_t attIndex = 0; attIndex < m_colorAttachmentCount; ++attIndex)
842     {
843         barrier.image = **images[attIndex];
844         commandBuffer = allocateCommandBuffer(vk, device, *commandPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY);
845         cmdBuffer     = *commandBuffer;
846 
847         beginCommandBuffer(vk, cmdBuffer);
848         vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, 0, 0,
849                               0, 1, &barrier);
850         vk.cmdCopyImageToBuffer(cmdBuffer, barrier.image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **attBuffer, 1,
851                                 &region);
852         endCommandBuffer(vk, cmdBuffer);
853 
854         submitCommandsAndWait(vk, device, queue, cmdBuffer);
855 
856         const Allocation &bufferAllocation = attBuffer->getAllocation();
857         invalidateAlloc(vk, device, bufferAllocation);
858         const uint32_t *bufferPtr = static_cast<uint32_t *>(bufferAllocation.getHostPtr());
859         log << tcu::TestLog::Message << "Color attachment " << attIndex << " contains: " << bufferPtr[0]
860             << tcu::TestLog::EndMessage;
861     }
862 
863     return tcu::TestStatus::fail("Fail");
864 }
865 
866 class MappingWithBlendStateTestInstance : public vkt::TestInstance
867 {
868 public:
869     MappingWithBlendStateTestInstance(Context &context, const TestType testType);
870 
871 protected:
872     tcu::TestStatus iterate(void) override;
873 
874 private:
875     const uint32_t m_renderSize;
876 };
877 
MappingWithBlendStateTestInstance(Context & context,const TestType testType)878 MappingWithBlendStateTestInstance::MappingWithBlendStateTestInstance(Context &context, const TestType testType)
879     : vkt::TestInstance(context)
880     , m_renderSize(16)
881 {
882     DE_UNREF(testType);
883 }
884 
iterate()885 tcu::TestStatus MappingWithBlendStateTestInstance::iterate()
886 {
887     const DeviceInterface &vk              = m_context.getDeviceInterface();
888     const VkDevice device                  = m_context.getDevice();
889     Allocator &memAlloc                    = m_context.getDefaultAllocator();
890     VkQueue queue                          = m_context.getUniversalQueue();
891     const uint32_t queueFamilyIndex        = m_context.getUniversalQueueFamilyIndex();
892     const VkFormat imageFormat             = VK_FORMAT_R8G8B8A8_UNORM;
893     const tcu::TextureFormat textureFormat = mapVkFormat(imageFormat);
894     const uint32_t colorAttachmentCount    = 4u;
895 
896     const VkImageSubresourceRange colorSRR = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
897     const VkImageSubresourceLayers colorSL = makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
898     const VkBufferImageCopy copyRegion     = makeBufferImageCopy({m_renderSize, m_renderSize, 1u}, colorSL);
899 
900     Move<VkCommandPool> commandPool =
901         createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
902     Move<VkCommandBuffer> commandBuffer =
903         allocateCommandBuffer(vk, device, *commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
904     VkCommandBuffer cmdBuffer = *commandBuffer;
905 
906     const std::vector<VkViewport> viewports{makeViewport(m_renderSize, m_renderSize)};
907     const std::vector<VkRect2D> scissors{makeRect2D(m_renderSize, m_renderSize)};
908 
909     const tcu::Vec4 clearValues[] // blend src color
910         {
911             {0.5f, 0.5f, 0.4f, 1.0f},
912             {0.2f, 0.4f, 0.3f, 0.1f},
913             {0.2f, 1.0f, 0.5f, 0.8f},
914             {1.0f, 0.1f, 0.3f, 0.5f},
915         };
916     DE_ASSERT(DE_LENGTH_OF_ARRAY(clearValues) == colorAttachmentCount);
917 
918     const VkPipelineColorBlendAttachmentState colorBlendAttachmentStates[]{
919         {1, VK_BLEND_FACTOR_SRC_ALPHA, VK_BLEND_FACTOR_DST_ALPHA, VK_BLEND_OP_ADD, VK_BLEND_FACTOR_SRC_ALPHA,
920          VK_BLEND_FACTOR_DST_ALPHA, VK_BLEND_OP_MAX, 0xf},
921         {1, VK_BLEND_FACTOR_ONE, VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA, VK_BLEND_OP_SUBTRACT,
922          VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, VK_BLEND_FACTOR_DST_ALPHA, VK_BLEND_OP_ADD, 0xf},
923         {1, VK_BLEND_FACTOR_ONE, VK_BLEND_FACTOR_ONE, VK_BLEND_OP_MIN, VK_BLEND_FACTOR_SRC_ALPHA,
924          VK_BLEND_FACTOR_DST_ALPHA, VK_BLEND_OP_MAX, 0xf},
925         {1, VK_BLEND_FACTOR_SRC_COLOR, VK_BLEND_FACTOR_DST_COLOR, VK_BLEND_OP_MAX, VK_BLEND_FACTOR_SRC_ALPHA,
926          VK_BLEND_FACTOR_DST_ALPHA, VK_BLEND_OP_MIN, 0xf},
927     };
928     DE_ASSERT(DE_LENGTH_OF_ARRAY(colorBlendAttachmentStates) == colorAttachmentCount);
929 
930     const uint32_t colorAttachmentLocations[]{3, 0, 2, 1};
931     DE_ASSERT(DE_LENGTH_OF_ARRAY(colorAttachmentLocations) == colorAttachmentCount);
932 
933     VkRenderingAttachmentInfo colorAttachment{
934         VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,           // VkStructureType sType;
935         DE_NULL,                                               // const void* pNext;
936         DE_NULL,                                               // VkImageView imageView;
937         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,              // VkImageLayout imageLayout;
938         VK_RESOLVE_MODE_NONE,                                  // VkResolveModeFlagBits resolveMode;
939         DE_NULL,                                               // VkImageView resolveImageView;
940         VK_IMAGE_LAYOUT_UNDEFINED,                             // VkImageLayout resolveImageLayout;
941         VK_ATTACHMENT_LOAD_OP_CLEAR,                           // VkAttachmentLoadOp loadOp;
942         VK_ATTACHMENT_STORE_OP_STORE,                          // VkAttachmentStoreOp storeOp;
943         makeClearValueColor(tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)) // VkClearValue clearValue;
944     };
945     VkImageMemoryBarrier imageMemoryBarrier =
946         makeImageMemoryBarrier(0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
947                                VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, DE_NULL, colorSRR);
948     const VkDeviceSize outputBufferSize = (VkDeviceSize)m_renderSize * m_renderSize * tcu::getPixelSize(textureFormat);
949     const VkBufferCreateInfo outputBufferInfo =
950         makeBufferCreateInfo(outputBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
951 
952     // construct required containers
953     std::vector<ImageWithMemorySp> images(colorAttachmentCount, ImageWithMemorySp());
954     std::vector<VkImageViewSp> imageViews(colorAttachmentCount, VkImageViewSp());
955     std::vector<VkFormat> colorImageFormats(colorAttachmentCount, imageFormat);
956     std::vector<VkRenderingAttachmentInfo> colorAttachments(colorAttachmentCount, colorAttachment);
957     std::vector<VkImageMemoryBarrier> colorImageBarriers(colorAttachmentCount, imageMemoryBarrier);
958     std::vector<BufferWithMemorySp> outputBuffers(colorAttachmentCount, BufferWithMemorySp());
959 
960     for (uint32_t i = 0; i < colorAttachmentCount; ++i)
961     {
962         // create images and image views for input attachments
963         images[i]     = createImage(m_context, m_renderSize, imageFormat,
964                                     VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
965         imageViews[i] = VkImageViewSp(new vk::Move<VkImageView>(
966             makeImageView(vk, device, **images[i], VK_IMAGE_VIEW_TYPE_2D, imageFormat, colorSRR)));
967 
968         colorAttachments[i].imageView  = **imageViews[i];
969         colorAttachments[i].clearValue = makeClearValueColor(clearValues[i]);
970         colorImageBarriers[i].image    = **images[i];
971 
972         // create output buffers that will be used to get attachments data
973         outputBuffers[i] = BufferWithMemorySp(
974             new BufferWithMemory(vk, device, memAlloc, outputBufferInfo, MemoryRequirement::HostVisible));
975     }
976 
977     Move<VkPipelineLayout> pipelineLayout = makePipelineLayout(vk, device, DE_NULL);
978     Move<VkShaderModule> vertShaderModule =
979         createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0);
980     Move<VkShaderModule> fragShaderModule =
981         createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0);
982 
983     // define empty VertexInputState, full screen quad will be generated in vertex shader
984     const VkPipelineVertexInputStateCreateInfo vertexInputState = initVulkanStructure();
985 
986     // define ColorBlendState so that we can write to multiple color attachments
987     VkPipelineColorBlendStateCreateInfo colorBlendStateCreateInfo = initVulkanStructure();
988     colorBlendStateCreateInfo.attachmentCount                     = colorAttachmentCount;
989     colorBlendStateCreateInfo.pAttachments                        = colorBlendAttachmentStates;
990 
991     VkRenderingAttachmentLocationInfoKHR renderingAttachmentLocations{
992         VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_LOCATION_INFO_KHR, DE_NULL, colorAttachmentCount,
993         colorAttachmentLocations};
994     VkPipelineRenderingCreateInfo renderingCreateInfo{VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
995                                                       &renderingAttachmentLocations,
996                                                       0u,
997                                                       colorAttachmentCount,
998                                                       colorImageFormats.data(),
999                                                       VK_FORMAT_UNDEFINED,
1000                                                       VK_FORMAT_UNDEFINED};
1001 
1002     Move<VkPipeline> graphicsPipeline = makeGraphicsPipeline(
1003         vk, device, *pipelineLayout, *vertShaderModule, DE_NULL, DE_NULL, DE_NULL, *fragShaderModule, DE_NULL,
1004         viewports, scissors, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 0, 0, &vertexInputState, DE_NULL, DE_NULL, DE_NULL,
1005         &colorBlendStateCreateInfo, DE_NULL, &renderingCreateInfo);
1006 
1007     VkRenderingInfo renderingInfo{
1008         VK_STRUCTURE_TYPE_RENDERING_INFO,
1009         DE_NULL,
1010         0u,                      // VkRenderingFlags                        flags
1011         scissors[0],             // VkRect2D                                renderArea
1012         1u,                      // uint32_t                                layerCount
1013         0u,                      // uint32_t                                viewMask
1014         colorAttachmentCount,    // uint32_t                                colorAttachmentCount
1015         colorAttachments.data(), // const VkRenderingAttachmentInfo*        pColorAttachments
1016         DE_NULL,                 // const VkRenderingAttachmentInfo*        pDepthAttachment
1017         DE_NULL                  // const VkRenderingAttachmentInfo*        pStencilAttachment
1018     };
1019 
1020     // record primary command buffer
1021     beginCommandBuffer(vk, cmdBuffer);
1022 
1023     // transfer layout to color attachment optimal
1024     vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_NONE, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, 0u,
1025                           0u, 0u, colorAttachmentCount, colorImageBarriers.data());
1026 
1027     vk.cmdBeginRendering(cmdBuffer, &renderingInfo);
1028 
1029     // remaping should affect to which attachments shader writes but not blend state
1030     vk.cmdSetRenderingAttachmentLocationsKHR(cmdBuffer, &renderingAttachmentLocations);
1031 
1032     vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline);
1033     vk.cmdDraw(cmdBuffer, 4u, 1u, 0u, 0u);
1034 
1035     vk.cmdEndRendering(cmdBuffer);
1036 
1037     // transition colorbuffers layout to transfer source optimal
1038     for (uint32_t i = 0; i < colorAttachmentCount; ++i)
1039     {
1040         colorImageBarriers[i].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
1041         colorImageBarriers[i].dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
1042         colorImageBarriers[i].oldLayout     = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
1043         colorImageBarriers[i].newLayout     = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
1044     }
1045     vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1046                           0u, 0u, 0u, 0u, colorAttachmentCount, colorImageBarriers.data());
1047 
1048     // read back color images
1049     for (uint32_t i = 0; i < colorAttachmentCount; ++i)
1050         vk.cmdCopyImageToBuffer(cmdBuffer, **images[i], VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **outputBuffers[i], 1u,
1051                                 &copyRegion);
1052 
1053     endCommandBuffer(vk, cmdBuffer);
1054     submitCommandsAndWait(vk, device, queue, cmdBuffer);
1055 
1056     const tcu::Vec4 expectedLeftSideColors[]{
1057         {0.50f, 0.98f, 0.72f, 1.00f},
1058         {0.42f, 0.44f, 0.63f, 0.17f},
1059         {0.10f, 0.30f, 0.50f, 0.80f},
1060         {1.00f, 0.40f, 0.30f, 0.50f},
1061     };
1062     DE_ASSERT(DE_LENGTH_OF_ARRAY(expectedLeftSideColors) == colorAttachmentCount);
1063 
1064     bool testPassed(true);
1065     const tcu::Vec4 colorPrecision(0.05f);
1066     auto &log(m_context.getTestContext().getLog());
1067 
1068     // verify result
1069     for (uint32_t i = 0; i < colorAttachmentCount; ++i)
1070     {
1071         bool colorIsCorrect = true;
1072         auto &allocation    = outputBuffers[i]->getAllocation();
1073         invalidateAlloc(vk, device, allocation);
1074 
1075         tcu::ConstPixelBufferAccess outputAccess(textureFormat, m_renderSize, m_renderSize, 1u,
1076                                                  allocation.getHostPtr());
1077 
1078         // check one fragment from the left side of image (after blending)
1079         tcu::Vec4 fragmentColorOnLeftSide = outputAccess.getPixel(i, i, 0);
1080         if (tcu::boolAny(
1081                 tcu::greaterThan(tcu::absDiff(fragmentColorOnLeftSide, expectedLeftSideColors[i]), colorPrecision)))
1082             colorIsCorrect = false;
1083 
1084         // check one fragment from the right side of image (clear color should be there)
1085         tcu::Vec4 fragmentColorOnRightSide(outputAccess.getPixel(m_renderSize - 1 - i, m_renderSize - 1 - i, 0));
1086         if (tcu::boolAny(tcu::greaterThan(tcu::absDiff(fragmentColorOnRightSide, clearValues[i]), colorPrecision)))
1087             colorIsCorrect = false;
1088 
1089         if (!colorIsCorrect)
1090         {
1091             std::string imageName = std::string("Attachment") + std::to_string(i);
1092             log << tcu::TestLog::Image(imageName, imageName, outputAccess);
1093             testPassed = false;
1094         }
1095     }
1096 
1097     if (testPassed)
1098         return tcu::TestStatus::pass("Pass");
1099 
1100     return tcu::TestStatus::fail("Fail");
1101 }
1102 
1103 class LocalReadTestCase : public vkt::TestCase
1104 {
1105 public:
1106     LocalReadTestCase(tcu::TestContext &context, const std::string &name, TestType testType);
1107     virtual ~LocalReadTestCase(void) = default;
1108 
1109 protected:
1110     void checkSupport(Context &context) const override;
1111     void initPrograms(SourceCollections &programCollection) const override;
1112     TestInstance *createInstance(Context &context) const override;
1113 
1114     TestType m_testType;
1115 };
1116 
LocalReadTestCase(tcu::TestContext & context,const std::string & name,TestType testType)1117 LocalReadTestCase::LocalReadTestCase(tcu::TestContext &context, const std::string &name, TestType testType)
1118     : vkt::TestCase(context, name)
1119     , m_testType(testType)
1120 {
1121 }
1122 
checkSupport(Context & context) const1123 void LocalReadTestCase::checkSupport(Context &context) const
1124 {
1125     context.requireDeviceFunctionality("VK_KHR_dynamic_rendering_local_read");
1126 
1127     if (m_testType == TestType::INTERACTION_WITH_COLOR_WRITE_ENABLE)
1128         context.requireDeviceFunctionality("VK_EXT_color_write_enable");
1129     else if (m_testType == TestType::INTERACTION_WITH_EXTENDED_DYNAMIC_STATE3)
1130     {
1131         context.requireDeviceFunctionality("VK_EXT_extended_dynamic_state3");
1132         if (!context.getExtendedDynamicState3FeaturesEXT().extendedDynamicState3RasterizationSamples)
1133             TCU_THROW(NotSupportedError, "extendedDynamicState3RasterizationSamples not supported");
1134     }
1135 }
1136 
initPrograms(SourceCollections & programCollection) const1137 void LocalReadTestCase::initPrograms(SourceCollections &programCollection) const
1138 {
1139     // vertex shader generates fullscreen quad
1140     std::string vertSrc("#version 450\n"
1141                         "void main (void)\n"
1142                         "{\n"
1143                         "  const float x = (-1.0+2.0*((gl_VertexIndex & 2)>>1));\n"
1144                         "  const float y = ( 1.0-2.0* (gl_VertexIndex % 2));\n"
1145                         "  gl_Position = vec4(x, y, 0.6, 1.0);\n"
1146                         "}\n");
1147     auto &glslSources = programCollection.glslSources;
1148     glslSources.add("vert") << glu::VertexSource(vertSrc);
1149 
1150     // helper lambda that generates fragment shader that writes to specified number of color attachments
1151     auto generateWriteFragSource = [](uint32_t colorAttachmentCount)
1152     {
1153         std::stringstream fragSrc;
1154         fragSrc << "#version 450\n"
1155                    "layout(push_constant) uniform InputDraw {\n"
1156                    "  uint count;\n"
1157                    "} inputDraw;\n";
1158         for (uint32_t i = 0; i < colorAttachmentCount; ++i)
1159             fragSrc << "layout(location=" << i << ") out uint outColor" << i << ";\n";
1160         fragSrc << "void main()\n{\n";
1161         for (uint32_t i = 0; i < colorAttachmentCount; ++i)
1162         {
1163             fragSrc << "  outColor" << i << " = 2u * inputDraw.count + " << i + 1 << ";\n";
1164             fragSrc << "  outColor" << i << " *= "
1165                     << "outColor" << i << ";\n";
1166         }
1167         fragSrc << "}\n";
1168         return fragSrc.str();
1169     };
1170 
1171     // helper lambda that generates fragment shader that reads from specified number of input attachments
1172     auto generateReadFragSource = [](uint32_t inputAttachmentCount, bool useStencil = true)
1173     {
1174         uint32_t colorInputAttachmentCount = inputAttachmentCount - 1u - useStencil;
1175         std::stringstream fragSrc;
1176         fragSrc << "#version 450\n";
1177         for (uint32_t i = 0; i < colorInputAttachmentCount; ++i)
1178             fragSrc << "layout(input_attachment_index=" << i << ", binding=" << i << ") uniform usubpassInput inColor"
1179                     << i << ";\n";
1180 
1181         fragSrc << "layout(input_attachment_index = " << colorInputAttachmentCount
1182                 << ", binding = " << colorInputAttachmentCount << ") uniform subpassInput inDepth;\n";
1183         if (useStencil)
1184             fragSrc << "layout(input_attachment_index = " << colorInputAttachmentCount + 1
1185                     << ", binding = " << colorInputAttachmentCount + 1 << ") uniform usubpassInput inStencil;\n";
1186 
1187         fragSrc << "layout(set=1, binding=0, std430) writeonly buffer Output\n{\n"
1188                    "  uint v[];\n"
1189                    "} outBuffer;\n"
1190                    "void main()\n{\n"
1191                    "  uint result = 0;\n";
1192         for (uint32_t i = 0; i < colorInputAttachmentCount; ++i)
1193             fragSrc << "  result = result + " << i + 1 << " * subpassLoad(inColor" << i << ").x; \n";
1194         fragSrc << "  result = result + uint(subpassLoad(inDepth).x * 1000);\n"; // 0.6*1000
1195         if (useStencil)
1196             fragSrc << "  result = result + uint(subpassLoad(inStencil).x * 1000);\n"; // 1 * 1000
1197         fragSrc << "  const uvec2 i = uvec2(trunc(gl_FragCoord.xy));\n"
1198                    "  outBuffer.v[i.x+i.y*16] = result;\n"
1199                    "}\n";
1200         return fragSrc.str();
1201     };
1202 
1203     if (m_testType == TestType::MAX_INPUT_ATTACHMENTS)
1204     {
1205         // generate fragment shader for maximal number of input attachments;
1206         // during test execution proper shader will be picked
1207         for (uint32_t inputAttachmentCount : inputAttachmentsPossibleValues)
1208         {
1209             // subtract 2 because we will write to depth and stencil and those
1210             // attachments will later consume 2 input attachment slots
1211             uint32_t colorAttachmentCount = inputAttachmentCount - 2u;
1212             glslSources.add(std::string("frag0_") + std::to_string(colorAttachmentCount))
1213                 << glu::FragmentSource(generateWriteFragSource(colorAttachmentCount));
1214         }
1215     }
1216     else if (m_testType == TestType::MAX_ATTACHMENTS_REMAPPED_REPEATEDLY)
1217     {
1218         glslSources.add("frag0") << glu::FragmentSource(generateWriteFragSource(2));
1219     }
1220     else if (m_testType == TestType::UNUSED_WRITEN_DISCARDED)
1221     {
1222         glslSources.add("frag0") << glu::FragmentSource(generateWriteFragSource(4));
1223         glslSources.add("frag1") << glu::FragmentSource(generateReadFragSource(6));
1224     }
1225     else if (m_testType == TestType::DEPTH_STENCIL_MAPPING_TO_NO_INDEX)
1226     {
1227         glslSources.add("frag0") << glu::FragmentSource(generateWriteFragSource(2));
1228 
1229         // Per spec, if either of pDepthInputAttachmentIndex or pStencilInputAttachmentIndex are set to
1230         // NULL it means that these are only accessible in the shader if the shader does not associate
1231         // these input attachments with an InputAttachmentIndex.
1232 
1233         // NOTE at the memoment glslang doesn't support input attachments without
1234         // input_attachment_index qualifiers
1235 
1236         //std::string fragSrc(
1237         //    "#version 450\n"
1238         //    "layout(input_attachment_index=0, binding=0) uniform usubpassInput inColor0;\n"
1239         //    "layout(input_attachment_index=1, binding=1) uniform usubpassInput inColor1;\n"
1240         //    "layout(binding=2) uniform  subpassInput inDepth;\n"
1241         //    "layout(binding=3) uniform usubpassInput inStencil;\n"
1242         //    "layout(set=1, binding=0, std430) writeonly buffer Output\n{\n"
1243         //    "  uint v[];\n"
1244         //    "} outBuffer;\n"
1245         //    "void main()\n{\n"
1246         //    "  uint result = subpassLoad(inColor0).x + subpassLoad(inColor1).x;\n"    // 1 + 2
1247         //    "  result = result + uint(subpassLoad(inDepth).x * 1000);\n"            // 0.6*1000
1248         //    "  result = result + uint(subpassLoad(inStencil).x * 100);\n"            // 1*100
1249         //    "  const uvec2 i = uvec2(trunc(gl_FragCoord.xy));\n"
1250         //    "  outBuffer.v[i.x+i.y*16] = result;\n"
1251         // "}\n");
1252         //glslSources.add("frag1") << glu::FragmentSource(fragSrc);
1253 
1254         programCollection.spirvAsmSources.add("frag1") << "OpCapability Shader\n"
1255                                                           "OpCapability InputAttachment\n"
1256                                                           "%1 = OpExtInstImport \"GLSL.std.450\";\n"
1257                                                           "OpMemoryModel Logical GLSL450\n"
1258                                                           "OpEntryPoint Fragment %4 \"main\" %51\n"
1259                                                           "OpExecutionMode %4 OriginUpperLeft\n"
1260                                                           "OpDecorate %11 DescriptorSet 0\n"
1261                                                           "OpDecorate %11 Binding 0\n"
1262                                                           "OpDecorate %11 InputAttachmentIndex 0\n"
1263                                                           "OpDecorate %21 DescriptorSet 0\n"
1264                                                           "OpDecorate %21 Binding 1\n"
1265                                                           "OpDecorate %21 InputAttachmentIndex 1\n"
1266                                                           "OpDecorate %30 DescriptorSet 0\n"
1267                                                           "OpDecorate %30 Binding 2\n"
1268                                                           //"OpDecorate %30 InputAttachmentIndex 2\n"
1269                                                           "OpDecorate %40 DescriptorSet 0\n"
1270                                                           "OpDecorate %40 Binding 3\n"
1271                                                           //"OpDecorate %40 InputAttachmentIndex 3\n"
1272                                                           "OpDecorate %51 BuiltIn FragCoord\n"
1273                                                           "OpDecorate %57 ArrayStride 4\n"
1274                                                           "OpMemberDecorate %58 0 NonReadable\n"
1275                                                           "OpMemberDecorate %58 0 Offset 0\n"
1276                                                           "OpDecorate %58 BufferBlock\n"
1277                                                           "OpDecorate %60 DescriptorSet 1\n"
1278                                                           "OpDecorate %60 Binding 0\n"
1279                                                           "%2 = OpTypeVoid\n"
1280                                                           "%3 = OpTypeFunction %2\n"
1281                                                           "%6 = OpTypeInt 32 0\n"
1282                                                           "%7 = OpTypePointer Function %6\n"
1283                                                           "%9 = OpTypeImage %6 SubpassData 0 0 0 2 Unknown\n"
1284                                                           "%10 = OpTypePointer UniformConstant %9\n"
1285                                                           "%11 = OpVariable %10 UniformConstant\n"
1286                                                           "%13 = OpTypeInt 32 1\n"
1287                                                           "%14 = OpConstant %13 0\n"
1288                                                           "%15 = OpTypeVector %13 2\n"
1289                                                           "%16 = OpConstantComposite %15 %14 %14\n"
1290                                                           "%17 = OpTypeVector %6 4\n"
1291                                                           "%19 = OpConstant %6 0\n"
1292                                                           "%21 = OpVariable %10 UniformConstant\n"
1293                                                           "%27 = OpTypeFloat 32\n"
1294                                                           "%28 = OpTypeImage %27 SubpassData 0 0 0 2 Unknown\n"
1295                                                           "%29 = OpTypePointer UniformConstant %28\n"
1296                                                           "%30 = OpVariable %29 UniformConstant\n"
1297                                                           "%32 = OpTypeVector %27 4\n"
1298                                                           "%35 = OpConstant %27 1000\n"
1299                                                           "%40 = OpVariable %10 UniformConstant\n"
1300                                                           "%44 = OpConstant %6 100\n"
1301                                                           "%47 = OpTypeVector %6 2\n"
1302                                                           "%48 = OpTypePointer Function %47\n"
1303                                                           "%50 = OpTypePointer Input %32\n"
1304                                                           "%51 = OpVariable %50 Input\n"
1305                                                           "%52 = OpTypeVector %27 2\n"
1306                                                           "%57 = OpTypeRuntimeArray %6\n"
1307                                                           "%58 = OpTypeStruct %57\n"
1308                                                           "%59 = OpTypePointer Uniform %58\n"
1309                                                           "%60 = OpVariable %59 Uniform\n"
1310                                                           "%63 = OpConstant %6 1\n"
1311                                                           "%66 = OpConstant %6 16\n"
1312                                                           "%70 = OpTypePointer Uniform %6\n"
1313                                                           "%4 = OpFunction %2 None %3\n"
1314                                                           "%5 = OpLabel\n"
1315                                                           "%8 = OpVariable %7 Function\n"
1316                                                           "%49 = OpVariable %48 Function\n"
1317                                                           "%12 = OpLoad %9 %11\n"
1318                                                           "%18 = OpImageRead %17 %12 %16\n"
1319                                                           "%20 = OpCompositeExtract %6 %18 0\n"
1320                                                           "%22 = OpLoad %9 %21\n"
1321                                                           "%23 = OpImageRead %17 %22 %16\n"
1322                                                           "%24 = OpCompositeExtract %6 %23 0\n"
1323                                                           "%25 = OpIAdd %6 %20 %24\n"
1324                                                           "OpStore %8 %25\n"
1325                                                           "%26 = OpLoad %6 %8\n"
1326                                                           "%31 = OpLoad %28 %30\n"
1327                                                           "%33 = OpImageRead %32 %31 %16\n"
1328                                                           "%34 = OpCompositeExtract %27 %33 0\n"
1329                                                           "%36 = OpFMul %27 %34 %35\n"
1330                                                           "%37 = OpConvertFToU %6 %36\n"
1331                                                           "%38 = OpIAdd %6 %26 %37\n"
1332                                                           "OpStore %8 %38\n"
1333                                                           "%39 = OpLoad %6 %8\n"
1334                                                           "%41 = OpLoad %9 %40\n"
1335                                                           "%42 = OpImageRead %17 %41 %16\n"
1336                                                           "%43 = OpCompositeExtract %6 %42 0\n"
1337                                                           "%45 = OpIMul %6 %43 %44\n"
1338                                                           "%46 = OpIAdd %6 %39 %45\n"
1339                                                           "OpStore %8 %46\n"
1340                                                           "%53 = OpLoad %32 %51\n"
1341                                                           "%54 = OpVectorShuffle %52 %53 %53 0 1\n"
1342                                                           "%55 = OpExtInst %52 %1 Trunc %54\n"
1343                                                           "%56 = OpConvertFToU %47 %55\n"
1344                                                           "OpStore %49 %56\n"
1345                                                           "%61 = OpAccessChain %7 %49 %19\n"
1346                                                           "%62 = OpLoad %6 %61\n"
1347                                                           "%64 = OpAccessChain %7 %49 %63\n"
1348                                                           "%65 = OpLoad %6 %64\n"
1349                                                           "%67 = OpIMul %6 %65 %66\n"
1350                                                           "%68 = OpIAdd %6 %62 %67\n"
1351                                                           "%69 = OpLoad %6 %8\n"
1352                                                           "%71 = OpAccessChain %70 %60 %14 %68\n"
1353                                                           "OpStore %71 %69\n"
1354                                                           "OpReturn\n"
1355                                                           "OpFunctionEnd\n";
1356     }
1357     else if ((m_testType == TestType::DEPTH_MAPPING_STENCIL_NOT) ||
1358              (m_testType == TestType::INTERACTION_WITH_COLOR_WRITE_ENABLE) ||
1359              (m_testType == TestType::INTERACTION_WITH_EXTENDED_DYNAMIC_STATE3))
1360     {
1361         glslSources.add("frag0") << glu::FragmentSource(generateWriteFragSource(4));
1362         glslSources.add("frag1") << glu::FragmentSource(generateReadFragSource(5, false));
1363     }
1364     else if (m_testType == TestType::DEPTH_STENCIL_MAPPING_TO_SAME_INDEX)
1365     {
1366         std::string fragSrc(
1367             "#version 450\n"
1368             "layout(input_attachment_index = 0, binding = 0) uniform usubpassInput inColor0;\n"
1369             "layout(input_attachment_index = 1, binding = 1) uniform usubpassInput inColor1;\n"
1370             "layout(input_attachment_index = 2, binding = 2) uniform  subpassInput inDepth;\n"
1371             "layout(input_attachment_index = 2, binding = 3) uniform usubpassInput inStencil;\n"
1372             "layout(set=1, binding=0, std430) writeonly buffer Output\n{\n"
1373             "  uint v[];\n"
1374             "} outBuffer;\n"
1375             "void main()\n{\n"
1376             "  const uvec2 i = uvec2(trunc(gl_FragCoord.xy));\n"
1377             "  outBuffer.v[i.x+i.y*16] = uint(subpassLoad(inDepth).x * 1000) + subpassLoad(inStencil).x;\n"
1378             "}\n");
1379         glslSources.add("frag0") << glu::FragmentSource(generateWriteFragSource(2));
1380         glslSources.add("frag1") << glu::FragmentSource(fragSrc);
1381     }
1382 
1383     if ((m_testType == TestType::MAX_INPUT_ATTACHMENTS) ||
1384         (m_testType == TestType::MAX_ATTACHMENTS_REMAPPED_REPEATEDLY))
1385     {
1386         // generate fragment shaders for all posible number of input attachments;
1387         // during test execution proper shader will be picked
1388         for (uint32_t inputAttachmentCount : inputAttachmentsPossibleValues)
1389             glslSources.add(std::string("frag1_") + std::to_string(inputAttachmentCount))
1390                 << glu::FragmentSource(generateReadFragSource(inputAttachmentCount));
1391     }
1392 
1393     if (m_testType == TestType::MAPPING_NOT_AFFECTING_BLEND_STATE)
1394     {
1395         std::string fragSrc("#version 450\n"
1396                             "layout(location = 0) out vec4 outColor0;\n"
1397                             "layout(location = 1) out vec4 outColor1;\n"
1398                             "layout(location = 2) out vec4 outColor2;\n"
1399                             "layout(location = 3) out vec4 outColor3;\n"
1400                             "void main()\n{\n"
1401                             "  if (gl_FragCoord.x > 8.0)\n"
1402                             "    discard;\n"
1403                             "  outColor0 = vec4(0.6, 0.8, 0.9, 0.2);\n" // used for attachment 1
1404                             "  outColor1 = vec4(0.6, 0.4, 0.2, 0.6);\n" // used for attachment 3
1405                             "  outColor2 = vec4(0.1, 0.3, 0.6, 0.2);\n" // used for attachment 2
1406                             "  outColor3 = vec4(0.0, 0.6, 0.4, 0.8);\n" // used for attachment 0
1407                             "}\n");
1408         glslSources.add("frag") << glu::FragmentSource(fragSrc);
1409     }
1410 }
1411 
createInstance(Context & context) const1412 TestInstance *LocalReadTestCase::createInstance(Context &context) const
1413 {
1414     if (m_testType == TestType::MAPPING_NOT_AFFECTING_BLEND_STATE)
1415         return new MappingWithBlendStateTestInstance(context, m_testType);
1416 
1417     return new BasicLocalReadTestInstance(context, m_testType);
1418 }
1419 
1420 } // namespace
1421 
createDynamicRenderingLocalReadTests(tcu::TestContext & testCtx)1422 tcu::TestCaseGroup *createDynamicRenderingLocalReadTests(tcu::TestContext &testCtx)
1423 {
1424     struct TestConfig
1425     {
1426         std::string name;
1427         TestType testType;
1428     };
1429     std::vector<TestConfig> testConfigs{
1430         {"max_input_attachments", TestType::MAX_INPUT_ATTACHMENTS},
1431         {"max_attachments_remapped_repeatedly", TestType::MAX_ATTACHMENTS_REMAPPED_REPEATEDLY},
1432         {"unused_writen_discarded", TestType::UNUSED_WRITEN_DISCARDED},
1433         {"depth_stencil_mapping_to_no_index", TestType::DEPTH_STENCIL_MAPPING_TO_NO_INDEX},
1434         {"depth_stencil_mapping_to_same_index", TestType::DEPTH_STENCIL_MAPPING_TO_SAME_INDEX},
1435         {"depth_mapping_stencil_not", TestType::DEPTH_MAPPING_STENCIL_NOT},
1436         {"mapping_not_affecting_blend_state", TestType::MAPPING_NOT_AFFECTING_BLEND_STATE},
1437         {"interaction_with_color_write_enable", TestType::INTERACTION_WITH_COLOR_WRITE_ENABLE},
1438         {"interaction_with_extended_dynamic_state3", TestType::INTERACTION_WITH_EXTENDED_DYNAMIC_STATE3},
1439     };
1440 
1441     de::MovePtr<tcu::TestCaseGroup> mainGroup(
1442         new tcu::TestCaseGroup(testCtx, "local_read", "Test dynamic rendering local read"));
1443 
1444     for (const auto &testConfig : testConfigs)
1445         mainGroup->addChild(new LocalReadTestCase(testCtx, testConfig.name, testConfig.testType));
1446 
1447     return mainGroup.release();
1448 }
1449 
1450 } // namespace renderpass
1451 } // namespace vkt
1452