1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2019 The Khronos Group Inc.
6  * Copyright (c) 2018 Google Inc.
7  * Copyright (c) 2015 Imagination Technologies Ltd.
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 Tests sparse input attachments in VkSubpassDescription::pInputAttachments
24  *//*--------------------------------------------------------------------*/
25 
26 #include "vktRenderPassUnusedAttachmentSparseFillingTests.hpp"
27 #include "vktRenderPassTestsUtil.hpp"
28 #include "vktTestCase.hpp"
29 #include "vkImageUtil.hpp"
30 #include "vkBarrierUtil.hpp"
31 #include "vkBuilderUtil.hpp"
32 #include "vkQueryUtil.hpp"
33 #include "vkCmdUtil.hpp"
34 #include "vkObjUtil.hpp"
35 #include "tcuTestLog.hpp"
36 #include "deRandom.hpp"
37 #include <sstream>
38 #include <vector>
39 #include <algorithm>
40 #include <numeric>
41 #include <random>
42 
43 typedef de::SharedPtr<vk::Unique<vk::VkImage>> VkImageSp;
44 typedef de::SharedPtr<vk::Unique<vk::VkImageView>> VkImageViewSp;
45 typedef de::SharedPtr<vk::Unique<vk::VkBuffer>> VkBufferSp;
46 typedef de::SharedPtr<vk::Allocation> AllocationSp;
47 
48 namespace vkt
49 {
50 
51 namespace renderpass
52 {
53 
54 using namespace vk;
55 
56 template <typename T>
safeSharedPtr(T * ptr)57 de::SharedPtr<T> safeSharedPtr(T *ptr)
58 {
59     try
60     {
61         return de::SharedPtr<T>(ptr);
62     }
63     catch (...)
64     {
65         delete ptr;
66         throw;
67     }
68 }
69 
70 static const uint32_t RENDER_SIZE      = 8u;
71 static const unsigned int DEFAULT_SEED = 31u;
72 
73 namespace
74 {
75 
76 struct TestParams
77 {
78     SharedGroupParams groupParams;
79     uint32_t activeInputAttachmentCount;
80 };
81 
82 struct Vertex
83 {
84     tcu::Vec4 position;
85     tcu::Vec4 uv;
86 };
87 
createFullscreenTriangle(void)88 std::vector<Vertex> createFullscreenTriangle(void)
89 {
90     std::vector<Vertex> vertices;
91 
92     for (uint32_t i = 0; i < 3; ++i)
93     {
94         float x = static_cast<float>((i << 1) & 2);
95         float y = static_cast<float>(i & 2);
96         vertices.push_back(
97             Vertex{tcu::Vec4(x * 2.0f - 1.0f, y * 2.0f - 1.0f, 0.0f, 1.0f), tcu::Vec4(x, y, 0.0f, 0.0f)});
98     }
99     return vertices;
100 }
101 
generateInputAttachmentParams(RenderingType renderingType,uint32_t activeAttachmentCount,uint32_t allAttachmentCount,std::vector<uint32_t> & attachmentIndices,std::vector<uint32_t> & descriptorBindings)102 void generateInputAttachmentParams(RenderingType renderingType, uint32_t activeAttachmentCount,
103                                    uint32_t allAttachmentCount, std::vector<uint32_t> &attachmentIndices,
104                                    std::vector<uint32_t> &descriptorBindings)
105 {
106     DE_ASSERT(attachmentIndices.empty());
107     DE_ASSERT(descriptorBindings.empty());
108 
109     attachmentIndices.resize(allAttachmentCount, VK_ATTACHMENT_UNUSED);
110     descriptorBindings.resize(activeAttachmentCount + 1, VK_ATTACHMENT_UNUSED);
111 
112     de::Random random(DEFAULT_SEED);
113 
114     // there is diference in test logic for dynamic rendering cases where attachment indices
115     // needed to be from range <0; 2 * activeAttachmentCount - 1> where for renderpass cases
116     // attachment indices had to be from range <0; activeAttachmentCount - 1>
117     if (renderingType == RENDERING_TYPE_DYNAMIC_RENDERING)
118     {
119         // fill all indices and shuffle them
120         std::iota(begin(attachmentIndices), end(attachmentIndices), 0);
121         random.shuffle(begin(attachmentIndices), end(attachmentIndices));
122 
123         // set every other attachment as unused
124         for (uint32_t i = 0; i < (uint32_t)attachmentIndices.size(); i += 2)
125             attachmentIndices[i] = VK_ATTACHMENT_UNUSED;
126 
127         // shuffle once again
128         random.shuffle(begin(attachmentIndices), end(attachmentIndices));
129 
130         for (uint32_t i = 0, lastBinding = 1; i < allAttachmentCount; ++i)
131         {
132             if (attachmentIndices[i] != VK_ATTACHMENT_UNUSED)
133                 descriptorBindings[lastBinding++] = attachmentIndices[i];
134         }
135     }
136     else
137     {
138         // fill half of indices
139         std::iota(begin(attachmentIndices), begin(attachmentIndices) + activeAttachmentCount, 0);
140 
141         // shuffle values with remaining unused indices
142         random.shuffle(begin(attachmentIndices), end(attachmentIndices));
143 
144         for (uint32_t i = 0, lastBinding = 1; i < allAttachmentCount; ++i)
145         {
146             if (attachmentIndices[i] != VK_ATTACHMENT_UNUSED)
147                 descriptorBindings[lastBinding++] = i;
148         }
149     }
150 }
151 
chooseInputImageLayout(const SharedGroupParams groupParams)152 VkImageLayout chooseInputImageLayout(const SharedGroupParams groupParams)
153 {
154 #ifndef CTS_USES_VULKANSC
155     if (groupParams->renderingType == RENDERING_TYPE_DYNAMIC_RENDERING)
156     {
157         // use general layout for local reads for some tests
158         if (groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
159             return VK_IMAGE_LAYOUT_GENERAL;
160         return VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ_KHR;
161     }
162 #else
163     DE_UNREF(groupParams);
164 #endif
165     return VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
166 }
167 
168 #ifndef CTS_USES_VULKANSC
beginSecondaryCmdBuffer(const DeviceInterface & vk,VkCommandBuffer secCmdBuffer,std::vector<VkFormat> colorAttachmentFormats,const void * additionalInheritanceRenderingInfo=DE_NULL,VkCommandBufferUsageFlags usageFlags=0)169 void beginSecondaryCmdBuffer(const DeviceInterface &vk, VkCommandBuffer secCmdBuffer,
170                              std::vector<VkFormat> colorAttachmentFormats,
171                              const void *additionalInheritanceRenderingInfo = DE_NULL,
172                              VkCommandBufferUsageFlags usageFlags           = 0)
173 {
174     const VkCommandBufferInheritanceRenderingInfoKHR inheritanceRenderingInfo{
175         VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR, // VkStructureType sType;
176         additionalInheritanceRenderingInfo,                              // const void* pNext;
177         0u,                                                              // VkRenderingFlagsKHR flags;
178         0u,                                                              // uint32_t viewMask;
179         (uint32_t)colorAttachmentFormats.size(),                         // uint32_t colorAttachmentCount;
180         colorAttachmentFormats.data(),                                   // const VkFormat* pColorAttachmentFormats;
181         VK_FORMAT_UNDEFINED,                                             // VkFormat depthAttachmentFormat;
182         VK_FORMAT_UNDEFINED,                                             // VkFormat stencilAttachmentFormat;
183         VK_SAMPLE_COUNT_1_BIT,                                           // VkSampleCountFlagBits rasterizationSamples;
184     };
185     const VkCommandBufferInheritanceInfo bufferInheritanceInfo{
186         VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, // VkStructureType sType;
187         &inheritanceRenderingInfo,                         // const void* pNext;
188         DE_NULL,                                           // VkRenderPass renderPass;
189         0u,                                                // uint32_t subpass;
190         DE_NULL,                                           // VkFramebuffer framebuffer;
191         VK_FALSE,                                          // VkBool32 occlusionQueryEnable;
192         (VkQueryControlFlags)0u,                           // VkQueryControlFlags queryFlags;
193         (VkQueryPipelineStatisticFlags)0u                  // VkQueryPipelineStatisticFlags pipelineStatistics;
194     };
195     usageFlags |= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
196     const VkCommandBufferBeginInfo commandBufBeginParams{
197         VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
198         DE_NULL,                                     // const void* pNext;
199         usageFlags,                                  // VkCommandBufferUsageFlags flags;
200         &bufferInheritanceInfo                       // const VkCommandBufferInheritanceInfo* pInheritanceInfo;
201     };
202     VK_CHECK(vk.beginCommandBuffer(secCmdBuffer, &commandBufBeginParams));
203 }
204 
getRenderingInputAttachmentIndexInfo(RenderingType renderingType,uint32_t activeAttachmentCount,std::vector<uint32_t> & inputAttachments)205 VkRenderingInputAttachmentIndexInfoKHR getRenderingInputAttachmentIndexInfo(RenderingType renderingType,
206                                                                             uint32_t activeAttachmentCount,
207                                                                             std::vector<uint32_t> &inputAttachments)
208 {
209     std::vector<uint32_t> unnededBindings;
210     generateInputAttachmentParams(renderingType, activeAttachmentCount, 2u * activeAttachmentCount, inputAttachments,
211                                   unnededBindings);
212 
213     return {
214         VK_STRUCTURE_TYPE_RENDERING_INPUT_ATTACHMENT_INDEX_INFO_KHR,
215         DE_NULL,
216         (uint32_t)inputAttachments.size(), // uint32_t                    colorAttachmentCount
217         inputAttachments.data(),           // const uint32_t*            pColorAttachmentInputIndices
218         DE_NULL,                           // uint32_t                    depthInputAttachmentIndex
219         DE_NULL,                           // uint32_t                    stencilInputAttachmentIndex
220     };
221 }
222 #endif
223 
224 class InputAttachmentSparseFillingTest : public vkt::TestCase
225 {
226 public:
227     InputAttachmentSparseFillingTest(tcu::TestContext &testContext, const std::string &name,
228                                      const TestParams &testParams);
229     virtual ~InputAttachmentSparseFillingTest(void) = default;
230     virtual void initPrograms(SourceCollections &sourceCollections) const;
231     virtual TestInstance *createInstance(Context &context) const;
232     virtual void checkSupport(Context &context) const;
233 
234 private:
235     TestParams m_testParams;
236 };
237 
238 class InputAttachmentSparseFillingTestInstance : public vkt::TestInstance
239 {
240 public:
241     InputAttachmentSparseFillingTestInstance(Context &context, const TestParams &testParams);
242     virtual ~InputAttachmentSparseFillingTestInstance(void) = default;
243     virtual tcu::TestStatus iterate(void);
244 
245 protected:
246     template <typename RenderpassSubpass>
247     void createCommandBuffer(const DeviceInterface &vk, VkDevice vkDevice);
248     void createCommandBufferDynamicRendering(const DeviceInterface &vk, VkDevice vkDevice);
249     void preRenderCommands(const DeviceInterface &vk, VkCommandBuffer cmdBuffer);
250     void drawCommands(const DeviceInterface &vk, VkCommandBuffer cmdBuffer);
251     void postRenderCommands(const DeviceInterface &vk, VkCommandBuffer cmdBuffer);
252 
253     template <typename AttachmentDesc, typename AttachmentRef, typename SubpassDesc, typename SubpassDep,
254               typename RenderPassCreateInfo>
255     Move<VkRenderPass> createRenderPass(const DeviceInterface &vk, VkDevice vkDevice);
256 
257 private:
258     tcu::TestStatus verifyImage(void);
259 
260     const tcu::UVec2 m_renderSize;
261     std::vector<Vertex> m_vertices;
262     TestParams m_testParams;
263 
264     std::vector<VkImageSp> m_inputImages;
265     std::vector<AllocationSp> m_inputImageMemory;
266     std::vector<VkImageViewSp> m_inputImageViews;
267     VkImageLayout m_inputImageReadLayout;
268 
269     VkImageSp m_outputImage;
270     AllocationSp m_outputImageMemory;
271     VkImageViewSp m_outputImageView;
272 
273     VkBufferSp m_outputBuffer;
274     AllocationSp m_outputBufferMemory;
275 
276     Move<VkDescriptorSetLayout> m_descriptorSetLayout;
277     Move<VkDescriptorPool> m_descriptorPool;
278     Move<VkDescriptorSet> m_descriptorSet;
279     Move<VkRenderPass> m_renderPass;
280     Move<VkFramebuffer> m_framebuffer;
281 
282     Move<VkBuffer> m_vertexBuffer;
283     de::MovePtr<Allocation> m_vertexBufferAlloc;
284 
285     PipelineLayoutWrapper m_pipelineLayout;
286     GraphicsPipelineWrapper m_graphicsPipeline;
287 
288     Move<VkCommandPool> m_cmdPool;
289     Move<VkCommandBuffer> m_cmdBuffer;
290     Move<VkCommandBuffer> m_secCmdBuffer;
291 };
292 
InputAttachmentSparseFillingTest(tcu::TestContext & testContext,const std::string & name,const TestParams & testParams)293 InputAttachmentSparseFillingTest::InputAttachmentSparseFillingTest(tcu::TestContext &testContext,
294                                                                    const std::string &name,
295                                                                    const TestParams &testParams)
296     : vkt::TestCase(testContext, name)
297     , m_testParams(testParams)
298 {
299 }
300 
initPrograms(SourceCollections & sourceCollections) const301 void InputAttachmentSparseFillingTest::initPrograms(SourceCollections &sourceCollections) const
302 {
303     std::ostringstream fragmentSource;
304 
305     sourceCollections.glslSources.add("vertex") << glu::VertexSource("#version 450\n"
306                                                                      "layout(location = 0) in vec4 position;\n"
307                                                                      "layout(location = 1) in vec4 uv;\n"
308                                                                      "layout(location = 0) out vec4 outUV;\n"
309                                                                      "void main (void)\n"
310                                                                      "{\n"
311                                                                      "    gl_Position = position;\n"
312                                                                      "    outUV = uv;\n"
313                                                                      "}\n");
314 
315     // We read from X input attachments randomly spread in input attachment array of size 2*X
316     std::ostringstream str;
317     str << "#version 450\n"
318         << "layout(location = 0) in vec4 inUV;\n"
319         << "layout(binding = 0, rg32ui) uniform uimage2D resultImage;\n";
320 
321     std::vector<uint32_t> attachmentIndices, descriptorBindings;
322     generateInputAttachmentParams(m_testParams.groupParams->renderingType, m_testParams.activeInputAttachmentCount,
323                                   2u * m_testParams.activeInputAttachmentCount, attachmentIndices, descriptorBindings);
324 
325     for (std::size_t i = 1; i < descriptorBindings.size(); ++i)
326         str << "layout(binding = " << i << ", input_attachment_index = " << descriptorBindings[i]
327             << ") uniform subpassInput attach" << i << ";\n";
328 
329     str << "void main (void)\n"
330         << "{\n"
331         << "    uvec4 result = uvec4(0);\n";
332 
333     for (std::size_t i = 1; i < descriptorBindings.size(); ++i)
334     {
335         str << "    result.x = result.x + 1;\n";
336         str << "    if(subpassLoad(attach" << i << ").x > 0.0)\n";
337         str << "        result.y = result.y + 1;\n";
338     }
339 
340     str << "    imageStore(resultImage, ivec2(imageSize(resultImage) * inUV.xy), result);\n"
341         << "}\n";
342 
343     sourceCollections.glslSources.add("fragment") << glu::FragmentSource(str.str());
344 }
345 
createInstance(Context & context) const346 TestInstance *InputAttachmentSparseFillingTest::createInstance(Context &context) const
347 {
348     return new InputAttachmentSparseFillingTestInstance(context, m_testParams);
349 }
350 
checkSupport(Context & context) const351 void InputAttachmentSparseFillingTest::checkSupport(Context &context) const
352 {
353     const InstanceInterface &vki                    = context.getInstanceInterface();
354     vk::VkPhysicalDevice physicalDevice             = context.getPhysicalDevice();
355     const vk::VkPhysicalDeviceProperties properties = vk::getPhysicalDeviceProperties(vki, physicalDevice);
356     const vk::VkPhysicalDeviceLimits &limits        = properties.limits;
357 
358     checkPipelineConstructionRequirements(vki, physicalDevice, m_testParams.groupParams->pipelineConstructionType);
359     if (m_testParams.groupParams->renderingType == RENDERING_TYPE_RENDERPASS2)
360         context.requireDeviceFunctionality("VK_KHR_create_renderpass2");
361     else if (m_testParams.groupParams->renderingType == RENDERING_TYPE_DYNAMIC_RENDERING)
362     {
363         context.requireDeviceFunctionality("VK_KHR_dynamic_rendering_local_read");
364         if ((2u * m_testParams.activeInputAttachmentCount) > limits.maxColorAttachments)
365             TCU_THROW(NotSupportedError, "Required number of color attachments not supported.");
366     }
367 
368     if (2u * m_testParams.activeInputAttachmentCount > limits.maxPerStageDescriptorInputAttachments)
369         TCU_THROW(NotSupportedError,
370                   "Input attachment count including unused elements exceeds maxPerStageDescriptorInputAttachments");
371 
372     if (2u * m_testParams.activeInputAttachmentCount > limits.maxPerStageResources)
373         TCU_THROW(NotSupportedError, "Input attachment count including unused elements exceeds maxPerStageResources");
374 }
375 
InputAttachmentSparseFillingTestInstance(Context & context,const TestParams & testParams)376 InputAttachmentSparseFillingTestInstance::InputAttachmentSparseFillingTestInstance(Context &context,
377                                                                                    const TestParams &testParams)
378     : vkt::TestInstance(context)
379     , m_renderSize(RENDER_SIZE, RENDER_SIZE)
380     , m_vertices(createFullscreenTriangle())
381     , m_testParams(testParams)
382     , m_inputImageReadLayout(chooseInputImageLayout(testParams.groupParams))
383     , m_graphicsPipeline(context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(),
384                          context.getDevice(), context.getDeviceExtensions(),
385                          m_testParams.groupParams->pipelineConstructionType)
386 {
387     const DeviceInterface &vk       = m_context.getDeviceInterface();
388     const VkDevice vkDevice         = m_context.getDevice();
389     const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
390     SimpleAllocator memAlloc(
391         vk, vkDevice,
392         getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
393     const VkComponentMapping componentMappingRGBA = {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G,
394                                                      VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A};
395 
396     {
397         VkImageCreateInfo inputImageParams{
398             VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                                   // VkStructureType sType;
399             DE_NULL,                                                               // const void* pNext;
400             0u,                                                                    // VkImageCreateFlags flags;
401             VK_IMAGE_TYPE_2D,                                                      // VkImageType imageType;
402             VK_FORMAT_R8G8B8A8_UNORM,                                              // VkFormat format;
403             {m_renderSize.x(), m_renderSize.y(), 1u},                              // VkExtent3D extent;
404             1u,                                                                    // uint32_t mipLevels;
405             1u,                                                                    // uint32_t arrayLayers;
406             VK_SAMPLE_COUNT_1_BIT,                                                 // VkSampleCountFlagBits samples;
407             VK_IMAGE_TILING_OPTIMAL,                                               // VkImageTiling tiling;
408             VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage;
409             VK_SHARING_MODE_EXCLUSIVE,                                             // VkSharingMode sharingMode;
410             1u,                                                                    // uint32_t queueFamilyIndexCount;
411             &queueFamilyIndex,        // const uint32_t* pQueueFamilyIndices;
412             VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
413         };
414 
415         if (m_testParams.groupParams->renderingType == RENDERING_TYPE_DYNAMIC_RENDERING)
416             inputImageParams.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
417 
418         VkImageViewCreateInfo inputAttachmentViewParams = {
419             VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,   // VkStructureType sType;
420             DE_NULL,                                    // const void* pNext;
421             0u,                                         // VkImageViewCreateFlags flags;
422             0,                                          // VkImage image;
423             VK_IMAGE_VIEW_TYPE_2D,                      // VkImageViewType viewType;
424             VK_FORMAT_R8G8B8A8_UNORM,                   // VkFormat format;
425             componentMappingRGBA,                       // VkChannelMapping channels;
426             {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u} // VkImageSubresourceRange subresourceRange;
427         };
428 
429         // Create input attachment images with image views
430         for (uint32_t imageNdx = 0; imageNdx < m_testParams.activeInputAttachmentCount; ++imageNdx)
431         {
432             auto inputImage = safeSharedPtr(new Unique<VkImage>(vk::createImage(vk, vkDevice, &inputImageParams)));
433 
434             auto inputImageAlloc = safeSharedPtr(
435                 memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, **inputImage), MemoryRequirement::Any)
436                     .release());
437             VK_CHECK(
438                 vk.bindImageMemory(vkDevice, **inputImage, inputImageAlloc->getMemory(), inputImageAlloc->getOffset()));
439 
440             inputAttachmentViewParams.image = **inputImage;
441             auto inputImageView =
442                 safeSharedPtr(new Unique<VkImageView>(createImageView(vk, vkDevice, &inputAttachmentViewParams)));
443 
444             m_inputImages.push_back(inputImage);
445             m_inputImageMemory.push_back(inputImageAlloc);
446             m_inputImageViews.push_back(inputImageView);
447         }
448     }
449 
450     {
451         const VkImageCreateInfo outputImageParams = {
452             VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,      // VkStructureType sType;
453             DE_NULL,                                  // const void* pNext;
454             0u,                                       // VkImageCreateFlags flags;
455             VK_IMAGE_TYPE_2D,                         // VkImageType imageType;
456             VK_FORMAT_R32G32_UINT,                    // VkFormat format;
457             {m_renderSize.x(), m_renderSize.y(), 1u}, // VkExtent3D extent;
458             1u,                                       // uint32_t mipLevels;
459             1u,                                       // uint32_t arrayLayers;
460             VK_SAMPLE_COUNT_1_BIT,                    // VkSampleCountFlagBits samples;
461             VK_IMAGE_TILING_OPTIMAL,                  // VkImageTiling tiling;
462             VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
463                 VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage;
464             VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode sharingMode;
465             1u,                                  // uint32_t queueFamilyIndexCount;
466             &queueFamilyIndex,                   // const uint32_t* pQueueFamilyIndices;
467             VK_IMAGE_LAYOUT_UNDEFINED            // VkImageLayout initialLayout;
468         };
469 
470         m_outputImage       = safeSharedPtr(new Unique<VkImage>(vk::createImage(vk, vkDevice, &outputImageParams)));
471         m_outputImageMemory = safeSharedPtr(
472             memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, **m_outputImage), MemoryRequirement::Any)
473                 .release());
474         VK_CHECK(vk.bindImageMemory(vkDevice, **m_outputImage, m_outputImageMemory->getMemory(),
475                                     m_outputImageMemory->getOffset()));
476 
477         VkImageViewCreateInfo inputAttachmentViewParams = {
478             VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,   // VkStructureType sType;
479             DE_NULL,                                    // const void* pNext;
480             0u,                                         // VkImageViewCreateFlags flags;
481             **m_outputImage,                            // VkImage image;
482             VK_IMAGE_VIEW_TYPE_2D,                      // VkImageViewType viewType;
483             VK_FORMAT_R32G32_UINT,                      // VkFormat format;
484             componentMappingRGBA,                       // VkChannelMapping channels;
485             {VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u} // VkImageSubresourceRange subresourceRange;
486         };
487         m_outputImageView =
488             safeSharedPtr(new Unique<VkImageView>(createImageView(vk, vkDevice, &inputAttachmentViewParams)));
489     }
490 
491     {
492         const VkDeviceSize outputBufferSizeBytes =
493             m_renderSize.x() * m_renderSize.y() * tcu::getPixelSize(mapVkFormat(VK_FORMAT_R32G32_UINT));
494         const VkBufferCreateInfo outputBufferParams = {
495             VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // sType
496             DE_NULL,                              // pNext
497             (VkBufferCreateFlags)0u,              // flags
498             outputBufferSizeBytes,                // size
499             VK_BUFFER_USAGE_TRANSFER_DST_BIT,     // usage
500             VK_SHARING_MODE_EXCLUSIVE,            // sharingMode
501             1u,                                   // queueFamilyIndexCount
502             &queueFamilyIndex,                    // pQueueFamilyIndices
503         };
504         m_outputBuffer       = safeSharedPtr(new Unique<VkBuffer>(createBuffer(vk, vkDevice, &outputBufferParams)));
505         m_outputBufferMemory = safeSharedPtr(
506             memAlloc
507                 .allocate(getBufferMemoryRequirements(vk, vkDevice, **m_outputBuffer), MemoryRequirement::HostVisible)
508                 .release());
509         VK_CHECK(vk.bindBufferMemory(vkDevice, **m_outputBuffer, m_outputBufferMemory->getMemory(),
510                                      m_outputBufferMemory->getOffset()));
511     }
512 
513     // Create render pass
514     if (testParams.groupParams->renderingType == RENDERING_TYPE_RENDERPASS_LEGACY)
515         m_renderPass = createRenderPass<AttachmentDescription1, AttachmentReference1, SubpassDescription1,
516                                         SubpassDependency1, RenderPassCreateInfo1>(vk, vkDevice);
517     else if (testParams.groupParams->renderingType == RENDERING_TYPE_RENDERPASS2)
518         m_renderPass = createRenderPass<AttachmentDescription2, AttachmentReference2, SubpassDescription2,
519                                         SubpassDependency2, RenderPassCreateInfo2>(vk, vkDevice);
520 
521     std::vector<VkDescriptorImageInfo> descriptorImageInfos;
522     std::vector<VkImageView> framebufferImageViews;
523     descriptorImageInfos.push_back(VkDescriptorImageInfo{
524         DE_NULL,                // VkSampleri sampler;
525         **m_outputImageView,    // VkImageView imageView;
526         VK_IMAGE_LAYOUT_GENERAL // VkImageLayout imageLayout;
527     });
528     for (auto &inputImageView : m_inputImageViews)
529     {
530         framebufferImageViews.push_back(**inputImageView);
531         descriptorImageInfos.push_back(VkDescriptorImageInfo{
532             DE_NULL,               // VkSampleri sampler;
533             **inputImageView,      // VkImageView imageView;
534             m_inputImageReadLayout // VkImageLayout imageLayout;
535         });
536     }
537 
538     // Create framebuffer if renderpass handle is valid
539     if (*m_renderPass != DE_NULL)
540     {
541         const VkFramebufferCreateInfo framebufferParams = {
542             VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,           // VkStructureType sType;
543             DE_NULL,                                             // const void* pNext;
544             0u,                                                  // VkFramebufferCreateFlags flags;
545             *m_renderPass,                                       // VkRenderPass renderPass;
546             static_cast<uint32_t>(framebufferImageViews.size()), // uint32_t attachmentCount;
547             framebufferImageViews.data(),                        // const VkImageView* pAttachments;
548             static_cast<uint32_t>(m_renderSize.x()),             // uint32_t width;
549             static_cast<uint32_t>(m_renderSize.y()),             // uint32_t height;
550             1u                                                   // uint32_t layers;
551         };
552 
553         m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
554     }
555 
556     // Create pipeline layout
557     {
558         DescriptorSetLayoutBuilder layoutBuilder;
559         // add output image storage
560         layoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_FRAGMENT_BIT);
561         // add input attachments
562         for (uint32_t imageNdx = 0; imageNdx < m_testParams.activeInputAttachmentCount; ++imageNdx)
563             layoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, VK_SHADER_STAGE_FRAGMENT_BIT);
564         m_descriptorSetLayout = layoutBuilder.build(vk, vkDevice);
565 
566         m_pipelineLayout = PipelineLayoutWrapper(m_testParams.groupParams->pipelineConstructionType, vk, vkDevice,
567                                                  *m_descriptorSetLayout);
568     }
569 
570     // Update descriptor set
571     {
572         m_descriptorPool = DescriptorPoolBuilder()
573                                .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1u)
574                                .addType(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, m_testParams.activeInputAttachmentCount)
575                                .build(vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
576 
577         const VkDescriptorSetAllocateInfo descriptorSetAllocateInfo = {
578             VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // VkStructureType                    sType
579             DE_NULL,                                        // const void*                        pNext
580             *m_descriptorPool,                              // VkDescriptorPool                    descriptorPool
581             1u,                                             // uint32_t                            descriptorSetCount
582             &m_descriptorSetLayout.get(),                   // const VkDescriptorSetLayout*        pSetLayouts
583         };
584         m_descriptorSet = allocateDescriptorSet(vk, vkDevice, &descriptorSetAllocateInfo);
585 
586         DescriptorSetUpdateBuilder builder;
587         builder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
588                             VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfos[0]);
589         for (uint32_t i = 1; i < static_cast<uint32_t>(descriptorImageInfos.size()); ++i)
590             builder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(i),
591                                 VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, &descriptorImageInfos[i]);
592         builder.update(vk, vkDevice);
593     }
594 
595     ShaderWrapper vertexShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("vertex"), 0);
596     ShaderWrapper fragmentShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("fragment"), 0);
597 
598     // Create pipelines
599     {
600         const VkVertexInputBindingDescription vertexInputBindingDescription = {
601             0u,                         // uint32_t binding;
602             sizeof(Vertex),             // uint32_t strideInBytes;
603             VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputStepRate inputRate;
604         };
605 
606         std::vector<VkVertexInputAttributeDescription> vertexInputAttributeDescription = {
607             {
608                 0u,                            // uint32_t location;
609                 0u,                            // uint32_t binding;
610                 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
611                 0u                             // uint32_t offset;
612             },
613             {
614                 1u,                            // uint32_t location;
615                 0u,                            // uint32_t binding;
616                 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
617                 offsetof(Vertex, uv)           // uint32_t offset;
618             }};
619 
620         const VkPipelineVertexInputStateCreateInfo vertexInputStateParams{
621             VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
622             DE_NULL,                                                   // const void* pNext;
623             0u,                                                        // VkPipelineVertexInputStateCreateFlags flags;
624             1u,                                                        // uint32_t vertexBindingDescriptionCount;
625             &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
626             static_cast<uint32_t>(vertexInputAttributeDescription.size()), // uint32_t vertexAttributeDescriptionCount;
627             vertexInputAttributeDescription
628                 .data() // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
629         };
630 
631         VkPipelineColorBlendAttachmentState colorBlendAttachmentState;
632         deMemset(&colorBlendAttachmentState, 0x00, sizeof(VkPipelineColorBlendAttachmentState));
633         colorBlendAttachmentState.colorWriteMask = 0xF;
634 
635         uint32_t colorAttachmentsCount = (*m_renderPass == DE_NULL) ? 2u * m_testParams.activeInputAttachmentCount : 1u;
636         const std::vector<VkPipelineColorBlendAttachmentState> colorBlendAttachmentStates(colorAttachmentsCount,
637                                                                                           colorBlendAttachmentState);
638         VkPipelineColorBlendStateCreateInfo colorBlendStateCreateInfoDefault = initVulkanStructure();
639         colorBlendStateCreateInfoDefault.attachmentCount = uint32_t(colorBlendAttachmentStates.size());
640         colorBlendStateCreateInfoDefault.pAttachments    = colorBlendAttachmentStates.data();
641 
642         PipelineRenderingCreateInfoWrapper renderingCreateInfoWrapper;
643         RenderingInputAttachmentIndexInfoWrapper renderingInputAttachmentIndexInfoWrapper;
644         const std::vector<VkViewport> viewports{makeViewport(m_renderSize)};
645         const std::vector<VkRect2D> scissors{makeRect2D(m_renderSize)};
646 
647 #ifndef CTS_USES_VULKANSC
648         std::vector<uint32_t> inputAttachments;
649         auto renderingInputAttachmentIndexInfo = getRenderingInputAttachmentIndexInfo(
650             m_testParams.groupParams->renderingType, m_testParams.activeInputAttachmentCount, inputAttachments);
651 
652         std::vector<VkFormat> colorAttachmentFormats(colorAttachmentsCount, VK_FORMAT_UNDEFINED);
653         for (uint32_t index = 0; index < colorAttachmentsCount; ++index)
654         {
655             if (inputAttachments[index] != VK_ATTACHMENT_UNUSED)
656                 colorAttachmentFormats[index] = VK_FORMAT_R8G8B8A8_UNORM;
657         }
658 
659         VkPipelineRenderingCreateInfo renderingCreateInfo{VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO,
660                                                           DE_NULL,
661                                                           0u,
662                                                           (uint32_t)colorAttachmentFormats.size(),
663                                                           colorAttachmentFormats.data(),
664                                                           VK_FORMAT_UNDEFINED,
665                                                           VK_FORMAT_UNDEFINED};
666 
667         if (*m_renderPass == DE_NULL)
668         {
669             renderingCreateInfoWrapper.ptr               = &renderingCreateInfo;
670             renderingInputAttachmentIndexInfoWrapper.ptr = &renderingInputAttachmentIndexInfo;
671         }
672 #endif // CTS_USES_VULKANSC
673 
674         m_graphicsPipeline.setDefaultMultisampleState()
675             .setDefaultDepthStencilState()
676             .setDefaultRasterizationState()
677             .setupVertexInputState(&vertexInputStateParams)
678             .setupPreRasterizationShaderState(viewports, scissors, m_pipelineLayout, *m_renderPass, 0u,
679                                               vertexShaderModule, 0u, ShaderWrapper(), ShaderWrapper(), ShaderWrapper(),
680                                               DE_NULL, DE_NULL, renderingCreateInfoWrapper, DE_NULL)
681             .setupFragmentShaderState(m_pipelineLayout, *m_renderPass, 0u, fragmentShaderModule, 0, 0, 0, 0, {},
682                                       renderingInputAttachmentIndexInfoWrapper)
683             .setupFragmentOutputState(*m_renderPass, 0u, &colorBlendStateCreateInfoDefault)
684             .setMonolithicPipelineLayout(m_pipelineLayout)
685             .buildPipeline();
686     }
687 
688     // Create vertex buffer
689     {
690         const VkBufferCreateInfo vertexBufferParams = {
691             VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,               // VkStructureType sType;
692             DE_NULL,                                            // const void* pNext;
693             0u,                                                 // VkBufferCreateFlags flags;
694             (VkDeviceSize)(sizeof(Vertex) * m_vertices.size()), // VkDeviceSize size;
695             VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,                  // VkBufferUsageFlags usage;
696             VK_SHARING_MODE_EXCLUSIVE,                          // VkSharingMode sharingMode;
697             1u,                                                 // uint32_t queueFamilyIndexCount;
698             &queueFamilyIndex                                   // const uint32_t* pQueueFamilyIndices;
699         };
700 
701         m_vertexBuffer      = createBuffer(vk, vkDevice, &vertexBufferParams);
702         m_vertexBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer),
703                                                 MemoryRequirement::HostVisible);
704         VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(),
705                                      m_vertexBufferAlloc->getOffset()));
706 
707         // Upload vertex data
708         deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex));
709         flushAlloc(vk, vkDevice, *m_vertexBufferAlloc);
710     }
711 
712     // Create command pool
713     m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
714 
715     // Create command buffer
716     if (testParams.groupParams->renderingType == RENDERING_TYPE_RENDERPASS_LEGACY)
717         createCommandBuffer<RenderpassSubpass1>(vk, vkDevice);
718     else if (testParams.groupParams->renderingType == RENDERING_TYPE_RENDERPASS2)
719         createCommandBuffer<RenderpassSubpass2>(vk, vkDevice);
720     else
721         createCommandBufferDynamicRendering(vk, vkDevice);
722 }
723 
724 template <typename RenderpassSubpass>
createCommandBuffer(const DeviceInterface & vk,VkDevice vkDevice)725 void InputAttachmentSparseFillingTestInstance::createCommandBuffer(const DeviceInterface &vk, VkDevice vkDevice)
726 {
727     m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
728 
729     beginCommandBuffer(vk, *m_cmdBuffer, 0u);
730 
731     preRenderCommands(vk, *m_cmdBuffer);
732 
733     // Render pass does not use clear values - input images were prepared beforehand
734     const VkRenderPassBeginInfo renderPassBeginInfo = {
735         VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
736         DE_NULL,                                  // const void* pNext;
737         *m_renderPass,                            // VkRenderPass renderPass;
738         *m_framebuffer,                           // VkFramebuffer framebuffer;
739         makeRect2D(m_renderSize),                 // VkRect2D renderArea;
740         0,                                        // uint32_t clearValueCount;
741         DE_NULL                                   // const VkClearValue* pClearValues;
742     };
743     const typename RenderpassSubpass::SubpassBeginInfo subpassBeginInfo(DE_NULL, VK_SUBPASS_CONTENTS_INLINE);
744     RenderpassSubpass::cmdBeginRenderPass(vk, *m_cmdBuffer, &renderPassBeginInfo, &subpassBeginInfo);
745 
746     drawCommands(vk, *m_cmdBuffer);
747 
748     const typename RenderpassSubpass::SubpassEndInfo subpassEndInfo(DE_NULL);
749     RenderpassSubpass::cmdEndRenderPass(vk, *m_cmdBuffer, &subpassEndInfo);
750 
751     postRenderCommands(vk, *m_cmdBuffer);
752 
753     endCommandBuffer(vk, *m_cmdBuffer);
754 }
755 
createCommandBufferDynamicRendering(const DeviceInterface & vk,VkDevice vkDevice)756 void InputAttachmentSparseFillingTestInstance::createCommandBufferDynamicRendering(const DeviceInterface &vk,
757                                                                                    VkDevice vkDevice)
758 {
759 #ifndef CTS_USES_VULKANSC
760 
761     std::vector<uint32_t> inputAttachments;
762     const auto renderingInputAttachmentIndexInfo = getRenderingInputAttachmentIndexInfo(
763         m_testParams.groupParams->renderingType, m_testParams.activeInputAttachmentCount, inputAttachments);
764 
765     uint32_t colorAttachmentCount = 2u * m_testParams.activeInputAttachmentCount;
766     std::vector<VkFormat> colorAttachmentFormats(colorAttachmentCount, VK_FORMAT_UNDEFINED);
767     std::vector<VkRenderingAttachmentInfo> colorAttachments(
768         colorAttachmentCount,
769         {
770             VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO, // VkStructureType sType;
771             DE_NULL,                                     // const void* pNext;
772             VK_NULL_HANDLE,                              // VkImageView imageView;
773             m_inputImageReadLayout,                      // VkImageLayout imageLayout;
774             VK_RESOLVE_MODE_NONE,                        // VkResolveModeFlagBits resolveMode;
775             DE_NULL,                                     // VkImageView resolveImageView;
776             VK_IMAGE_LAYOUT_UNDEFINED,                   // VkImageLayout resolveImageLayout;
777             VK_ATTACHMENT_LOAD_OP_LOAD,                  // VkAttachmentLoadOp loadOp;
778             VK_ATTACHMENT_STORE_OP_STORE,                // VkAttachmentStoreOp storeOp;
779             makeClearValueColorU32(0, 0, 0, 0)           // VkClearValue clearValue;
780         });
781     uint32_t imageViewIndex = 0;
782     for (uint32_t index = 0; index < (uint32_t)inputAttachments.size(); ++index)
783     {
784         if (inputAttachments[index] == VK_ATTACHMENT_UNUSED)
785             continue;
786 
787         colorAttachments[index].imageView = **m_inputImageViews[imageViewIndex];
788         colorAttachmentFormats[index]     = VK_FORMAT_R8G8B8A8_UNORM;
789         ++imageViewIndex;
790     }
791 
792     VkRenderingInfo renderingInfo{
793         VK_STRUCTURE_TYPE_RENDERING_INFO,
794         DE_NULL,
795         0,                                 // VkRenderingFlagsKHR flags;
796         makeRect2D(m_renderSize),          // VkRect2D renderArea;
797         1u,                                // uint32_t layerCount;
798         0u,                                // uint32_t viewMask;
799         (uint32_t)colorAttachments.size(), // uint32_t colorAttachmentCount;
800         colorAttachments.data(),           // const VkRenderingAttachmentInfoKHR* pColorAttachments;
801         DE_NULL,                           // const VkRenderingAttachmentInfoKHR* pDepthAttachment;
802         DE_NULL,                           // const VkRenderingAttachmentInfoKHR* pStencilAttachment;
803     };
804 
805     m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
806 
807     if (m_testParams.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
808     {
809         m_secCmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
810 
811         // record secondary command buffer
812         beginSecondaryCmdBuffer(vk, *m_secCmdBuffer, colorAttachmentFormats);
813         vk.cmdBeginRendering(*m_secCmdBuffer, &renderingInfo);
814         vk.cmdSetRenderingInputAttachmentIndicesKHR(*m_secCmdBuffer, &renderingInputAttachmentIndexInfo);
815         drawCommands(vk, *m_secCmdBuffer);
816         vk.cmdEndRendering(*m_secCmdBuffer);
817         endCommandBuffer(vk, *m_secCmdBuffer);
818 
819         // record primary command buffer
820         beginCommandBuffer(vk, *m_cmdBuffer);
821         preRenderCommands(vk, *m_cmdBuffer);
822         vk.cmdExecuteCommands(*m_cmdBuffer, 1u, &*m_secCmdBuffer);
823         postRenderCommands(vk, *m_cmdBuffer);
824         endCommandBuffer(vk, *m_cmdBuffer);
825     }
826     else if (m_testParams.groupParams->useSecondaryCmdBuffer)
827     {
828         m_secCmdBuffer      = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
829         renderingInfo.flags = VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT_KHR;
830 
831         // record secondary command buffer
832         beginSecondaryCmdBuffer(vk, *m_secCmdBuffer, colorAttachmentFormats, &renderingInputAttachmentIndexInfo,
833                                 VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT);
834         drawCommands(vk, *m_secCmdBuffer);
835         endCommandBuffer(vk, *m_secCmdBuffer);
836 
837         // record primary command buffer
838         beginCommandBuffer(vk, *m_cmdBuffer);
839         preRenderCommands(vk, *m_cmdBuffer);
840         vk.cmdBeginRendering(*m_cmdBuffer, &renderingInfo);
841         vk.cmdSetRenderingInputAttachmentIndicesKHR(*m_cmdBuffer, &renderingInputAttachmentIndexInfo);
842         vk.cmdExecuteCommands(*m_cmdBuffer, 1u, &*m_secCmdBuffer);
843         vk.cmdEndRendering(*m_cmdBuffer);
844         postRenderCommands(vk, *m_cmdBuffer);
845         endCommandBuffer(vk, *m_cmdBuffer);
846     }
847     else
848     {
849         beginCommandBuffer(vk, *m_cmdBuffer, 0u);
850         preRenderCommands(vk, *m_cmdBuffer);
851         vk.cmdBeginRendering(*m_cmdBuffer, &renderingInfo);
852 
853         vk.cmdSetRenderingInputAttachmentIndicesKHR(*m_cmdBuffer, &renderingInputAttachmentIndexInfo);
854         drawCommands(vk, *m_cmdBuffer);
855 
856         vk.cmdEndRendering(*m_cmdBuffer);
857         postRenderCommands(vk, *m_cmdBuffer);
858         endCommandBuffer(vk, *m_cmdBuffer);
859     }
860 #else
861     DE_UNREF(vk);
862     DE_UNREF(vkDevice);
863 #endif // CTS_USES_VULKANSC
864 }
865 
preRenderCommands(const DeviceInterface & vk,VkCommandBuffer cmdBuffer)866 void InputAttachmentSparseFillingTestInstance::preRenderCommands(const DeviceInterface &vk, VkCommandBuffer cmdBuffer)
867 {
868     VkImageSubresourceRange range = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
869     VkClearValue clearColor       = makeClearValueColorU32(0, 0, 0, 0);
870 
871     // clear output image (rg16ui) to (0,0), set image layout to GENERAL
872     VkImageMemoryBarrier imageBarrier = makeImageMemoryBarrier(
873         0u, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, **m_outputImage, range);
874     vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL,
875                           0u, DE_NULL, 1u, &imageBarrier);
876 
877     vk.cmdClearColorImage(cmdBuffer, **m_outputImage, VK_IMAGE_LAYOUT_GENERAL, &clearColor.color, 1, &range);
878 
879     imageBarrier = makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_WRITE_BIT,
880                                           VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL, **m_outputImage, range);
881     vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u, 0u,
882                           DE_NULL, 0u, DE_NULL, 1u, &imageBarrier);
883 
884     auto inputImageLayout = VK_IMAGE_LAYOUT_GENERAL;
885     if (m_testParams.groupParams->renderingType == RENDERING_TYPE_DYNAMIC_RENDERING)
886         inputImageLayout = m_inputImageReadLayout;
887 
888     // clear all input attachments (rgba8) to (1,1,1,1), set image layout to GENERAL or LOCAL_READ
889     clearColor = makeClearValueColorF32(1.0f, 1.0f, 1.0f, 1.0f);
890     for (auto &inputImage : m_inputImages)
891     {
892         imageBarrier = makeImageMemoryBarrier(0u, VK_ACCESS_MEMORY_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
893                                               VK_IMAGE_LAYOUT_GENERAL, **inputImage, range);
894         vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u,
895                               DE_NULL, 0u, DE_NULL, 1u, &imageBarrier);
896 
897         vk.cmdClearColorImage(cmdBuffer, **inputImage, VK_IMAGE_LAYOUT_GENERAL, &clearColor.color, 1, &range);
898 
899         imageBarrier = makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,
900                                               VK_IMAGE_LAYOUT_GENERAL, inputImageLayout, **inputImage, range);
901         vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u, 0u,
902                               DE_NULL, 0u, DE_NULL, 1u, &imageBarrier);
903     }
904 }
905 
drawCommands(const DeviceInterface & vk,VkCommandBuffer cmdBuffer)906 void InputAttachmentSparseFillingTestInstance::drawCommands(const DeviceInterface &vk, VkCommandBuffer cmdBuffer)
907 {
908     const VkDeviceSize vertexBufferOffset = 0;
909     vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_graphicsPipeline.getPipeline());
910     vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0u, 1u,
911                              &m_descriptorSet.get(), 0u, DE_NULL);
912     vk.cmdBindVertexBuffers(cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
913     vk.cmdDraw(cmdBuffer, (uint32_t)m_vertices.size(), 1, 0, 0);
914 }
915 
postRenderCommands(const DeviceInterface & vk,VkCommandBuffer cmdBuffer)916 void InputAttachmentSparseFillingTestInstance::postRenderCommands(const DeviceInterface &vk, VkCommandBuffer cmdBuffer)
917 {
918     copyImageToBuffer(vk, cmdBuffer, **m_outputImage, **m_outputBuffer, tcu::IVec2(m_renderSize.x(), m_renderSize.y()),
919                       VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL);
920 }
921 
922 template <typename AttachmentDesc, typename AttachmentRef, typename SubpassDesc, typename SubpassDep,
923           typename RenderPassCreateInfo>
createRenderPass(const DeviceInterface & vk,VkDevice vkDevice)924 Move<VkRenderPass> InputAttachmentSparseFillingTestInstance::createRenderPass(const DeviceInterface &vk,
925                                                                               VkDevice vkDevice)
926 {
927     const auto renderingType = m_testParams.groupParams->renderingType;
928     const VkImageAspectFlags aspectMask =
929         renderingType == RENDERING_TYPE_RENDERPASS_LEGACY ? 0 : VK_IMAGE_ASPECT_COLOR_BIT;
930     std::vector<AttachmentDesc> attachmentDescriptions;
931     std::vector<AttachmentRef> attachmentRefs;
932 
933     std::vector<uint32_t> attachmentIndices;
934     std::vector<uint32_t> descriptorBindings;
935     generateInputAttachmentParams(renderingType, m_testParams.activeInputAttachmentCount,
936                                   2u * m_testParams.activeInputAttachmentCount, attachmentIndices, descriptorBindings);
937 
938     for (uint32_t i = 0; i < m_testParams.activeInputAttachmentCount; ++i)
939     {
940         attachmentDescriptions.push_back(
941             AttachmentDesc(DE_NULL,                                 // const void*                        pNext
942                            (VkAttachmentDescriptionFlags)0,         // VkAttachmentDescriptionFlags        flags
943                            VK_FORMAT_R8G8B8A8_UNORM,                // VkFormat                            format
944                            VK_SAMPLE_COUNT_1_BIT,                   // VkSampleCountFlagBits            samples
945                            VK_ATTACHMENT_LOAD_OP_LOAD,              // VkAttachmentLoadOp                loadOp
946                            VK_ATTACHMENT_STORE_OP_STORE,            // VkAttachmentStoreOp                storeOp
947                            VK_ATTACHMENT_LOAD_OP_DONT_CARE,         // VkAttachmentLoadOp                stencilLoadOp
948                            VK_ATTACHMENT_STORE_OP_DONT_CARE,        // VkAttachmentStoreOp                stencilStoreOp
949                            VK_IMAGE_LAYOUT_GENERAL,                 // VkImageLayout                    initialLayout
950                            VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL // VkImageLayout                    finalLayout
951                            ));
952     }
953     for (std::size_t i = 0; i < attachmentIndices.size(); ++i)
954         attachmentRefs.push_back(AttachmentRef(DE_NULL,              // const void*            pNext
955                                                attachmentIndices[i], // uint32_t                attachment
956                                                VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // VkImageLayout        layout
957                                                aspectMask // VkImageAspectFlags    aspectMask
958                                                ));
959 
960     std::vector<SubpassDesc> subpassDescriptions = {
961         SubpassDesc(
962             DE_NULL,
963             (VkSubpassDescriptionFlags)0,                 // VkSubpassDescriptionFlags        flags
964             VK_PIPELINE_BIND_POINT_GRAPHICS,              // VkPipelineBindPoint                pipelineBindPoint
965             0u,                                           // uint32_t                            viewMask
966             static_cast<uint32_t>(attachmentRefs.size()), // uint32_t                            inputAttachmentCount
967             attachmentRefs.data(),                        // const VkAttachmentReference*        pInputAttachments
968             0u,                                           // uint32_t                            colorAttachmentCount
969             DE_NULL,                                      // const VkAttachmentReference*        pColorAttachments
970             DE_NULL,                                      // const VkAttachmentReference*        pResolveAttachments
971             DE_NULL,                                      // const VkAttachmentReference*        pDepthStencilAttachment
972             0u,                                           // uint32_t                            preserveAttachmentCount
973             DE_NULL                                       // const uint32_t*                    pPreserveAttachments
974             ),
975     };
976     std::vector<SubpassDep> subpassDependencies = {
977         SubpassDep(DE_NULL,
978                    0u,                                    // uint32_t                srcPass
979                    VK_SUBPASS_EXTERNAL,                   // uint32_t                dstPass
980                    VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, // VkPipelineStageFlags    srcStageMask
981                    VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT,   // VkPipelineStageFlags    dstStageMask
982                    VK_ACCESS_SHADER_WRITE_BIT,            // VkAccessFlags        srcAccessMask
983                    VK_ACCESS_INDIRECT_COMMAND_READ_BIT,   // VkAccessFlags        dstAccessMask
984                    0,                                     // VkDependencyFlags    flags
985                    0                                      // int32_t                viewOffset
986                    ),
987     };
988 
989     const RenderPassCreateInfo renderPassInfo(
990         DE_NULL,                                              // const void*                        pNext
991         (VkRenderPassCreateFlags)0,                           // VkRenderPassCreateFlags            flags
992         static_cast<uint32_t>(attachmentDescriptions.size()), // uint32_t                            attachmentCount
993         attachmentDescriptions.data(),                        // const VkAttachmentDescription*    pAttachments
994         static_cast<uint32_t>(subpassDescriptions.size()),    // uint32_t                            subpassCount
995         subpassDescriptions.data(),                           // const VkSubpassDescription*        pSubpasses
996         static_cast<uint32_t>(subpassDependencies.size()),    // uint32_t                            dependencyCount
997         subpassDependencies.data(),                           // const VkSubpassDependency*        pDependencies
998         0u,     // uint32_t                            correlatedViewMaskCount
999         DE_NULL // const uint32_t*                    pCorrelatedViewMasks
1000     );
1001 
1002     return renderPassInfo.createRenderPass(vk, vkDevice);
1003 }
1004 
iterate(void)1005 tcu::TestStatus InputAttachmentSparseFillingTestInstance::iterate(void)
1006 {
1007     const DeviceInterface &vk = m_context.getDeviceInterface();
1008     const VkDevice vkDevice   = m_context.getDevice();
1009     const VkQueue queue       = m_context.getUniversalQueue();
1010 
1011     submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
1012 
1013     return verifyImage();
1014 }
1015 
verifyImage(void)1016 tcu::TestStatus InputAttachmentSparseFillingTestInstance::verifyImage(void)
1017 {
1018     const DeviceInterface &vk = m_context.getDeviceInterface();
1019     const VkDevice vkDevice   = m_context.getDevice();
1020 
1021     invalidateAlloc(vk, vkDevice, *m_outputBufferMemory);
1022     const tcu::ConstPixelBufferAccess resultAccess(mapVkFormat(VK_FORMAT_R32G32_UINT), m_renderSize.x(),
1023                                                    m_renderSize.y(), 1u, m_outputBufferMemory->getHostPtr());
1024 
1025     // Log result image
1026     m_context.getTestContext().getLog() << tcu::TestLog::ImageSet("Result", "Result images")
1027                                         << tcu::TestLog::Image("Rendered", "Rendered image", resultAccess)
1028                                         << tcu::TestLog::EndImageSet;
1029 
1030     // Check the unused image data hasn't changed.
1031     for (int y = 0; y < resultAccess.getHeight(); y++)
1032         for (int x = 0; x < resultAccess.getWidth(); x++)
1033         {
1034             tcu::UVec4 color = resultAccess.getPixelUint(x, y);
1035             if (color.x() != m_testParams.activeInputAttachmentCount)
1036                 return tcu::TestStatus::fail("Wrong attachment count");
1037             if (color.y() != m_testParams.activeInputAttachmentCount)
1038                 return tcu::TestStatus::fail("Wrong active attachment count");
1039         }
1040 
1041     return tcu::TestStatus::pass("Pass");
1042 }
1043 
1044 } // namespace
1045 
createRenderPassUnusedAttachmentSparseFillingTests(tcu::TestContext & testCtx,const SharedGroupParams groupParams)1046 tcu::TestCaseGroup *createRenderPassUnusedAttachmentSparseFillingTests(tcu::TestContext &testCtx,
1047                                                                        const SharedGroupParams groupParams)
1048 {
1049     // Unused attachment tests
1050     de::MovePtr<tcu::TestCaseGroup> unusedAttTests(new tcu::TestCaseGroup(testCtx, "attachment_sparse_filling"));
1051 
1052     const std::vector<uint32_t> activeInputAttachmentCount{1u, 3u, 7u, 15u, 31u, 63u, 127u};
1053 
1054     for (std::size_t attachmentNdx = 0; attachmentNdx < activeInputAttachmentCount.size(); ++attachmentNdx)
1055     {
1056         TestParams testParams{groupParams, activeInputAttachmentCount[attachmentNdx]};
1057         unusedAttTests->addChild(new InputAttachmentSparseFillingTest(
1058             testCtx, std::string("input_attachment_") + de::toString(activeInputAttachmentCount[attachmentNdx]),
1059             testParams));
1060     }
1061 
1062     return unusedAttTests.release();
1063 }
1064 
1065 } // namespace renderpass
1066 
1067 } // namespace vkt
1068