xref: /aosp_15_r20/external/deqp/external/vulkancts/modules/vulkan/multiview/vktMultiViewRenderTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2017 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 Multi View Render Tests
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktMultiViewRenderTests.hpp"
25 #include "vktMultiViewRenderUtil.hpp"
26 #include "vktMultiViewRenderPassUtil.hpp"
27 #include "vktCustomInstancesDevices.hpp"
28 
29 #include "vktTestCase.hpp"
30 #include "vkBuilderUtil.hpp"
31 #include "vkRefUtil.hpp"
32 #include "vkQueryUtil.hpp"
33 #include "vkDeviceUtil.hpp"
34 #include "vkTypeUtil.hpp"
35 #include "vkPrograms.hpp"
36 #include "vkPlatform.hpp"
37 #include "vkMemUtil.hpp"
38 #include "vkImageUtil.hpp"
39 #include "vkCmdUtil.hpp"
40 #include "vkObjUtil.hpp"
41 #include "vkBarrierUtil.hpp"
42 
43 #include "tcuTestLog.hpp"
44 #include "tcuResource.hpp"
45 #include "tcuImageCompare.hpp"
46 #include "tcuCommandLine.hpp"
47 #include "tcuTextureUtil.hpp"
48 #include "tcuRGBA.hpp"
49 
50 #include "deRandom.hpp"
51 #include "deMath.h"
52 #include "deSharedPtr.hpp"
53 #ifdef CTS_USES_VULKANSC
54 #include "vkSafetyCriticalUtil.hpp"
55 #endif
56 
57 #include <algorithm>
58 #include <bitset>
59 
60 namespace vkt
61 {
62 namespace MultiView
63 {
64 namespace
65 {
66 
67 using namespace vk;
68 using de::MovePtr;
69 using de::UniquePtr;
70 using std::map;
71 using std::string;
72 using std::vector;
73 
74 enum TestType
75 {
76     TEST_TYPE_VIEW_MASK,
77     TEST_TYPE_VIEW_INDEX_IN_VERTEX,
78     TEST_TYPE_VIEW_INDEX_IN_FRAGMENT,
79     TEST_TYPE_VIEW_INDEX_IN_GEOMETRY,
80     TEST_TYPE_VIEW_INDEX_IN_TESELLATION,
81     TEST_TYPE_INPUT_ATTACHMENTS,
82     TEST_TYPE_INPUT_ATTACHMENTS_GEOMETRY,
83     TEST_TYPE_INSTANCED_RENDERING,
84     TEST_TYPE_INPUT_RATE_INSTANCE,
85     TEST_TYPE_DRAW_INDIRECT,
86     TEST_TYPE_DRAW_INDIRECT_INDEXED,
87     TEST_TYPE_DRAW_INDEXED,
88     TEST_TYPE_CLEAR_ATTACHMENTS,
89     TEST_TYPE_SECONDARY_CMD_BUFFER,
90     TEST_TYPE_SECONDARY_CMD_BUFFER_GEOMETRY,
91     TEST_TYPE_POINT_SIZE,
92     TEST_TYPE_MULTISAMPLE,
93     TEST_TYPE_QUERIES,
94     TEST_TYPE_NON_PRECISE_QUERIES,
95     TEST_TYPE_NON_PRECISE_QUERIES_WITH_AVAILABILITY,
96     TEST_TYPE_READBACK_WITH_IMPLICIT_CLEAR,
97     TEST_TYPE_READBACK_WITH_EXPLICIT_CLEAR,
98     TEST_TYPE_DEPTH,
99     TEST_TYPE_DEPTH_DIFFERENT_RANGES,
100     TEST_TYPE_STENCIL,
101     TEST_TYPE_VIEW_MASK_ITERATION,
102     TEST_TYPE_NESTED_CMD_BUFFER,
103     TEST_TYPE_LAST
104 };
105 
106 enum RenderingType
107 {
108     RENDERING_TYPE_RENDERPASS_LEGACY = 0,
109     RENDERING_TYPE_RENDERPASS2,
110     RENDERING_TYPE_DYNAMIC_RENDERING
111 };
112 
113 enum QueryType
114 {
115     QUERY_TYPE_GET_QUERY_POOL_RESULTS,
116     QUERY_TYPE_CMD_COPY_QUERY_POOL_RESULTS
117 };
118 
119 struct TestParameters
120 {
121     VkExtent3D extent;
122     vector<uint32_t> viewMasks;
123     TestType viewIndex;
124     VkSampleCountFlagBits samples;
125     VkFormat colorFormat;
126     QueryType queryType;
127     RenderingType renderingType;
128 
geometryShaderNeededvkt::MultiView::__anon1a8a4f580111::TestParameters129     bool geometryShaderNeeded(void) const
130     {
131         return ((TEST_TYPE_VIEW_INDEX_IN_GEOMETRY == viewIndex) ||
132                 (TEST_TYPE_INPUT_ATTACHMENTS_GEOMETRY == viewIndex) ||
133                 (TEST_TYPE_SECONDARY_CMD_BUFFER_GEOMETRY == viewIndex));
134     }
135 };
136 
137 const int TEST_POINT_SIZE_SMALL = 2;
138 const int TEST_POINT_SIZE_WIDE  = 4;
139 
makeRenderPass(const DeviceInterface & vk,const VkDevice device,const VkFormat colorFormat,const vector<uint32_t> & viewMasks,RenderingType renderingType,const VkSampleCountFlagBits samples=VK_SAMPLE_COUNT_1_BIT,const VkAttachmentLoadOp colorLoadOp=VK_ATTACHMENT_LOAD_OP_CLEAR,const VkFormat dsFormat=VK_FORMAT_UNDEFINED)140 vk::Move<vk::VkRenderPass> makeRenderPass(const DeviceInterface &vk, const VkDevice device, const VkFormat colorFormat,
141                                           const vector<uint32_t> &viewMasks, RenderingType renderingType,
142                                           const VkSampleCountFlagBits samples  = VK_SAMPLE_COUNT_1_BIT,
143                                           const VkAttachmentLoadOp colorLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
144                                           const VkFormat dsFormat              = VK_FORMAT_UNDEFINED)
145 {
146     switch (renderingType)
147     {
148     case RENDERING_TYPE_RENDERPASS_LEGACY:
149         return MultiView::makeRenderPass<AttachmentDescription1, AttachmentReference1, SubpassDescription1,
150                                          SubpassDependency1, RenderPassCreateInfo1>(vk, device, colorFormat, viewMasks,
151                                                                                     samples, colorLoadOp, dsFormat);
152     case RENDERING_TYPE_RENDERPASS2:
153         return MultiView::makeRenderPass<AttachmentDescription2, AttachmentReference2, SubpassDescription2,
154                                          SubpassDependency2, RenderPassCreateInfo2>(vk, device, colorFormat, viewMasks,
155                                                                                     samples, colorLoadOp, dsFormat);
156     default:
157         TCU_THROW(InternalError, "Impossible");
158     }
159 }
160 
makeRenderPassWithAttachments(const DeviceInterface & vk,const VkDevice device,const VkFormat colorFormat,const vector<uint32_t> & viewMasks,RenderingType renderingType)161 vk::Move<vk::VkRenderPass> makeRenderPassWithAttachments(const DeviceInterface &vk, const VkDevice device,
162                                                          const VkFormat colorFormat, const vector<uint32_t> &viewMasks,
163                                                          RenderingType renderingType)
164 {
165     switch (renderingType)
166     {
167     case RENDERING_TYPE_RENDERPASS_LEGACY:
168         return MultiView::makeRenderPassWithAttachments<AttachmentDescription1, AttachmentReference1,
169                                                         SubpassDescription1, SubpassDependency1, RenderPassCreateInfo1>(
170             vk, device, colorFormat, viewMasks, false);
171     case RENDERING_TYPE_RENDERPASS2:
172         return MultiView::makeRenderPassWithAttachments<AttachmentDescription2, AttachmentReference2,
173                                                         SubpassDescription2, SubpassDependency2, RenderPassCreateInfo2>(
174             vk, device, colorFormat, viewMasks, true);
175     default:
176         TCU_THROW(InternalError, "Impossible");
177     }
178 }
179 
makeRenderPassWithDepth(const DeviceInterface & vk,const VkDevice device,const VkFormat colorFormat,const vector<uint32_t> & viewMasks,const VkFormat dsFormat,RenderingType renderingType)180 vk::Move<vk::VkRenderPass> makeRenderPassWithDepth(const DeviceInterface &vk, const VkDevice device,
181                                                    const VkFormat colorFormat, const vector<uint32_t> &viewMasks,
182                                                    const VkFormat dsFormat, RenderingType renderingType)
183 {
184     switch (renderingType)
185     {
186     case RENDERING_TYPE_RENDERPASS_LEGACY:
187         return MultiView::makeRenderPassWithDepth<AttachmentDescription1, AttachmentReference1, SubpassDescription1,
188                                                   SubpassDependency1, RenderPassCreateInfo1>(vk, device, colorFormat,
189                                                                                              viewMasks, dsFormat);
190     case RENDERING_TYPE_RENDERPASS2:
191         return MultiView::makeRenderPassWithDepth<AttachmentDescription2, AttachmentReference2, SubpassDescription2,
192                                                   SubpassDependency2, RenderPassCreateInfo2>(vk, device, colorFormat,
193                                                                                              viewMasks, dsFormat);
194     default:
195         TCU_THROW(InternalError, "Impossible");
196     }
197 }
198 
199 template <typename RenderpassSubpass>
cmdBeginRenderPass(DeviceInterface & vkd,VkCommandBuffer cmdBuffer,const VkRenderPassBeginInfo * pRenderPassBegin,const VkSubpassContents contents)200 void cmdBeginRenderPass(DeviceInterface &vkd, VkCommandBuffer cmdBuffer, const VkRenderPassBeginInfo *pRenderPassBegin,
201                         const VkSubpassContents contents)
202 {
203     const typename RenderpassSubpass::SubpassBeginInfo subpassBeginInfo(DE_NULL, contents);
204 
205     RenderpassSubpass::cmdBeginRenderPass(vkd, cmdBuffer, pRenderPassBegin, &subpassBeginInfo);
206 }
207 
cmdBeginRenderPass(DeviceInterface & vkd,VkCommandBuffer cmdBuffer,const VkRenderPassBeginInfo * pRenderPassBegin,const VkSubpassContents contents,RenderingType renderingType)208 void cmdBeginRenderPass(DeviceInterface &vkd, VkCommandBuffer cmdBuffer, const VkRenderPassBeginInfo *pRenderPassBegin,
209                         const VkSubpassContents contents, RenderingType renderingType)
210 {
211     switch (renderingType)
212     {
213     case RENDERING_TYPE_RENDERPASS_LEGACY:
214         cmdBeginRenderPass<RenderpassSubpass1>(vkd, cmdBuffer, pRenderPassBegin, contents);
215         break;
216     case RENDERING_TYPE_RENDERPASS2:
217         cmdBeginRenderPass<RenderpassSubpass2>(vkd, cmdBuffer, pRenderPassBegin, contents);
218         break;
219     default:
220         TCU_THROW(InternalError, "Impossible");
221     }
222 }
223 
224 template <typename RenderpassSubpass>
cmdNextSubpass(DeviceInterface & vkd,VkCommandBuffer cmdBuffer,const VkSubpassContents contents)225 void cmdNextSubpass(DeviceInterface &vkd, VkCommandBuffer cmdBuffer, const VkSubpassContents contents)
226 {
227     const typename RenderpassSubpass::SubpassBeginInfo subpassBeginInfo(DE_NULL, contents);
228     const typename RenderpassSubpass::SubpassEndInfo subpassEndInfo(DE_NULL);
229 
230     RenderpassSubpass::cmdNextSubpass(vkd, cmdBuffer, &subpassBeginInfo, &subpassEndInfo);
231 }
232 
cmdNextSubpass(DeviceInterface & vkd,VkCommandBuffer cmdBuffer,const VkSubpassContents contents,RenderingType renderingType)233 void cmdNextSubpass(DeviceInterface &vkd, VkCommandBuffer cmdBuffer, const VkSubpassContents contents,
234                     RenderingType renderingType)
235 {
236     switch (renderingType)
237     {
238     case RENDERING_TYPE_RENDERPASS_LEGACY:
239         cmdNextSubpass<RenderpassSubpass1>(vkd, cmdBuffer, contents);
240         break;
241     case RENDERING_TYPE_RENDERPASS2:
242         cmdNextSubpass<RenderpassSubpass2>(vkd, cmdBuffer, contents);
243         break;
244     default:
245         TCU_THROW(InternalError, "Impossible");
246     }
247 }
248 
249 template <typename RenderpassSubpass>
cmdEndRenderPass(DeviceInterface & vkd,VkCommandBuffer cmdBuffer)250 void cmdEndRenderPass(DeviceInterface &vkd, VkCommandBuffer cmdBuffer)
251 {
252     const typename RenderpassSubpass::SubpassEndInfo subpassEndInfo(DE_NULL);
253 
254     RenderpassSubpass::cmdEndRenderPass(vkd, cmdBuffer, &subpassEndInfo);
255 }
256 
cmdEndRenderPass(DeviceInterface & vkd,VkCommandBuffer cmdBuffer,RenderingType renderingType)257 void cmdEndRenderPass(DeviceInterface &vkd, VkCommandBuffer cmdBuffer, RenderingType renderingType)
258 {
259     switch (renderingType)
260     {
261     case RENDERING_TYPE_RENDERPASS_LEGACY:
262         cmdEndRenderPass<RenderpassSubpass1>(vkd, cmdBuffer);
263         break;
264     case RENDERING_TYPE_RENDERPASS2:
265         cmdEndRenderPass<RenderpassSubpass2>(vkd, cmdBuffer);
266         break;
267     default:
268         TCU_THROW(InternalError, "Impossible");
269     }
270 }
271 
272 class ImageAttachment
273 {
274 public:
275     ImageAttachment(VkDevice logicalDevice, DeviceInterface &device, Allocator &allocator, const VkExtent3D extent,
276                     VkFormat colorFormat, const VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT);
getImageView(void) const277     VkImageView getImageView(void) const
278     {
279         return *m_imageView;
280     }
getImage(void) const281     VkImage getImage(void) const
282     {
283         return *m_image;
284     }
285 
286 private:
287     Move<VkImage> m_image;
288     MovePtr<Allocation> m_allocationImage;
289     Move<VkImageView> m_imageView;
290 };
291 
ImageAttachment(VkDevice logicalDevice,DeviceInterface & device,Allocator & allocator,const VkExtent3D extent,VkFormat colorFormat,const VkSampleCountFlagBits samples)292 ImageAttachment::ImageAttachment(VkDevice logicalDevice, DeviceInterface &device, Allocator &allocator,
293                                  const VkExtent3D extent, VkFormat colorFormat, const VkSampleCountFlagBits samples)
294 {
295     const bool depthStencilFormat = isDepthStencilFormat(colorFormat);
296     const VkImageAspectFlags aspectFlags =
297         depthStencilFormat ? VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT : VK_IMAGE_ASPECT_COLOR_BIT;
298     const VkImageSubresourceRange colorImageSubresourceRange =
299         makeImageSubresourceRange(aspectFlags, 0u, 1u, 0u, extent.depth);
300     const VkImageUsageFlags imageUsageFlagsDependent =
301         depthStencilFormat ? VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT : VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
302     const VkImageUsageFlags imageUsageFlags = imageUsageFlagsDependent | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
303                                               VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
304     const VkImageCreateInfo colorAttachmentImageInfo =
305         makeImageCreateInfo(VK_IMAGE_TYPE_2D, extent, colorFormat, imageUsageFlags, samples);
306 
307     m_image = createImage(device, logicalDevice, &colorAttachmentImageInfo);
308     m_allocationImage =
309         allocator.allocate(getImageMemoryRequirements(device, logicalDevice, *m_image), MemoryRequirement::Any);
310     VK_CHECK(device.bindImageMemory(logicalDevice, *m_image, m_allocationImage->getMemory(),
311                                     m_allocationImage->getOffset()));
312     m_imageView = makeImageView(device, logicalDevice, *m_image, VK_IMAGE_VIEW_TYPE_2D_ARRAY, colorFormat,
313                                 colorImageSubresourceRange);
314 }
315 
316 class MultiViewRenderTestInstance : public TestInstance
317 {
318 public:
319     MultiViewRenderTestInstance(Context &context, const TestParameters &parameters);
320     ~MultiViewRenderTestInstance();
321 
322 protected:
323     typedef de::SharedPtr<Unique<VkPipeline>> PipelineSp;
324     typedef de::SharedPtr<Unique<VkShaderModule>> ShaderModuleSP;
325 
326     virtual tcu::TestStatus iterate(void);
327     virtual void beforeRenderPass(void);
328     virtual void afterRenderPass(void);
bindResources(void)329     virtual void bindResources(void)
330     {
331     }
332     virtual void draw(const uint32_t subpassCount, VkRenderPass renderPass, VkFramebuffer frameBuffer,
333                       vector<PipelineSp> &pipelines);
334     virtual void createVertexData(void);
335     virtual MovePtr<tcu::Texture2DArray> imageData(void) const;
336     TestParameters fillMissingParameters(const TestParameters &parameters);
337     void createVertexBuffer(void);
338     void createMultiViewDevices(void);
339     void createCommandBuffer(void);
340     void createSecondaryCommandPool(void);
341     void madeShaderModule(map<VkShaderStageFlagBits, ShaderModuleSP> &shaderModule,
342                           vector<VkPipelineShaderStageCreateInfo> &shaderStageParams);
343     Move<VkPipeline> makeGraphicsPipeline(const VkRenderPass renderPass, const VkPipelineLayout pipelineLayout,
344                                           const uint32_t pipelineShaderStageCount,
345                                           const VkPipelineShaderStageCreateInfo *pipelineShaderStageCreate,
346                                           const uint32_t subpass,
347                                           const VkVertexInputRate vertexInputRate = VK_VERTEX_INPUT_RATE_VERTEX,
348                                           const bool useDepthTest = false, const bool useStencilTest = false,
349                                           const float minDepth = 0.0f, const float maxDepth = 1.0f,
350                                           const VkFormat dsFormat = VK_FORMAT_UNDEFINED);
351     void readImage(VkImage image, const tcu::PixelBufferAccess &dst);
352     bool checkImage(tcu::ConstPixelBufferAccess &dst);
353     const tcu::Vec4 getQuarterRefColor(const uint32_t quarterNdx, const int colorNdx, const int layerNdx,
354                                        const bool background = true, const uint32_t subpassNdx = 0u) const;
355     void appendVertex(const tcu::Vec4 &coord, const tcu::Vec4 &color);
356     void setPoint(const tcu::PixelBufferAccess &pixelBuffer, const tcu::Vec4 &pointColor, const int pointSize,
357                   const int layerNdx, const uint32_t quarter) const;
358     void fillTriangle(const tcu::PixelBufferAccess &pixelBuffer, const tcu::Vec4 &color, const int layerNdx,
359                       const uint32_t quarter) const;
360     void fillLayer(const tcu::PixelBufferAccess &pixelBuffer, const tcu::Vec4 &color, const int layerNdx) const;
361     void fillQuarter(const tcu::PixelBufferAccess &pixelBuffer, const tcu::Vec4 &color, const int layerNdx,
362                      const uint32_t quarter, const uint32_t subpassNdx) const;
363 #ifndef CTS_USES_VULKANSC
364     void addRenderingSubpassDependencyIfRequired(uint32_t currentSubpassNdx);
365 #endif // CTS_USES_VULKANSC
366 
367     const TestParameters m_parameters;
368     const bool m_useDynamicRendering;
369     const bool m_cmdCopyQueryPoolResults;
370     const int m_seed;
371     const uint32_t m_squareCount;
372 
373     Move<VkDevice> m_logicalDevice;
374 #ifndef CTS_USES_VULKANSC
375     de::MovePtr<vk::DeviceDriver> m_device;
376 #else
377     de::MovePtr<vk::DeviceDriverSC, vk::DeinitDeviceDeleter> m_device;
378 #endif // CTS_USES_VULKANSC
379     MovePtr<Allocator> m_allocator;
380     uint32_t m_queueFamilyIndex;
381     VkQueue m_queue;
382     vector<tcu::Vec4> m_vertexCoord;
383     Move<VkBuffer> m_vertexCoordBuffer;
384     MovePtr<Allocation> m_vertexCoordAlloc;
385     vector<tcu::Vec4> m_vertexColor;
386     Move<VkBuffer> m_vertexColorBuffer;
387     MovePtr<Allocation> m_vertexColorAlloc;
388     vector<uint32_t> m_vertexIndices;
389     Move<VkBuffer> m_vertexIndicesBuffer;
390     MovePtr<Allocation> m_vertexIndicesAllocation;
391     Move<VkCommandPool> m_cmdPool;
392     Move<VkCommandBuffer> m_cmdBuffer;
393     Move<VkCommandPool> m_cmdPoolSecondary;
394     de::SharedPtr<ImageAttachment> m_colorAttachment;
395     VkBool32 m_hasMultiDrawIndirect;
396     vector<tcu::Vec4> m_colorTable;
397 };
398 
MultiViewRenderTestInstance(Context & context,const TestParameters & parameters)399 MultiViewRenderTestInstance::MultiViewRenderTestInstance(Context &context, const TestParameters &parameters)
400     : TestInstance(context)
401     , m_parameters(fillMissingParameters(parameters))
402     , m_useDynamicRendering(parameters.renderingType == RENDERING_TYPE_DYNAMIC_RENDERING)
403     , m_cmdCopyQueryPoolResults(parameters.queryType == QUERY_TYPE_CMD_COPY_QUERY_POOL_RESULTS)
404     , m_seed(context.getTestContext().getCommandLine().getBaseSeed())
405     , m_squareCount(4u)
406     , m_queueFamilyIndex(0u)
407 {
408     const float v = 0.75f;
409     const float o = 0.25f;
410 
411     m_colorTable.push_back(tcu::Vec4(v, o, o, 1.0f));
412     m_colorTable.push_back(tcu::Vec4(o, v, o, 1.0f));
413     m_colorTable.push_back(tcu::Vec4(o, o, v, 1.0f));
414     m_colorTable.push_back(tcu::Vec4(o, v, v, 1.0f));
415     m_colorTable.push_back(tcu::Vec4(v, o, v, 1.0f));
416     m_colorTable.push_back(tcu::Vec4(v, v, o, 1.0f));
417     m_colorTable.push_back(tcu::Vec4(o, o, o, 1.0f));
418     m_colorTable.push_back(tcu::Vec4(v, v, v, 1.0f));
419 
420     createMultiViewDevices();
421 
422     // Color attachment
423     m_colorAttachment = de::SharedPtr<ImageAttachment>(
424         new ImageAttachment(*m_logicalDevice, *m_device, *m_allocator, m_parameters.extent, m_parameters.colorFormat,
425                             m_parameters.samples));
426 }
427 
~MultiViewRenderTestInstance()428 MultiViewRenderTestInstance::~MultiViewRenderTestInstance()
429 {
430 }
431 
iterate(void)432 tcu::TestStatus MultiViewRenderTestInstance::iterate(void)
433 {
434     const uint32_t subpassCount = static_cast<uint32_t>(m_parameters.viewMasks.size());
435     Move<VkRenderPass> renderPass;
436     Move<VkFramebuffer> frameBuffer;
437 
438     // FrameBuffer & renderPass
439     if (m_parameters.renderingType != RENDERING_TYPE_DYNAMIC_RENDERING)
440     {
441         renderPass  = makeRenderPass(*m_device, *m_logicalDevice, m_parameters.colorFormat, m_parameters.viewMasks,
442                                      m_parameters.renderingType);
443         frameBuffer = makeFramebuffer(*m_device, *m_logicalDevice, *renderPass, m_colorAttachment->getImageView(),
444                                       m_parameters.extent.width, m_parameters.extent.height);
445     }
446 
447     // pipelineLayout
448     Unique<VkPipelineLayout> pipelineLayout(makePipelineLayout(*m_device, *m_logicalDevice));
449 
450     // pipelines
451     map<VkShaderStageFlagBits, ShaderModuleSP> shaderModule;
452     vector<PipelineSp> pipelines(subpassCount);
453     const VkVertexInputRate vertexInputRate = (TEST_TYPE_INPUT_RATE_INSTANCE == m_parameters.viewIndex) ?
454                                                   VK_VERTEX_INPUT_RATE_INSTANCE :
455                                                   VK_VERTEX_INPUT_RATE_VERTEX;
456 
457     {
458         vector<VkPipelineShaderStageCreateInfo> shaderStageParams;
459         madeShaderModule(shaderModule, shaderStageParams);
460         for (uint32_t subpassNdx = 0u; subpassNdx < subpassCount; ++subpassNdx)
461             pipelines[subpassNdx] = (PipelineSp(new Unique<VkPipeline>(
462                 makeGraphicsPipeline(*renderPass, *pipelineLayout, static_cast<uint32_t>(shaderStageParams.size()),
463                                      shaderStageParams.data(), subpassNdx, vertexInputRate))));
464     }
465 
466     createCommandBuffer();
467     createVertexData();
468     createVertexBuffer();
469 
470     draw(subpassCount, *renderPass, *frameBuffer, pipelines);
471 
472     {
473         vector<uint8_t> pixelAccessData(m_parameters.extent.width * m_parameters.extent.height *
474                                         m_parameters.extent.depth *
475                                         mapVkFormat(m_parameters.colorFormat).getPixelSize());
476         tcu::PixelBufferAccess dst(mapVkFormat(m_parameters.colorFormat), m_parameters.extent.width,
477                                    m_parameters.extent.height, m_parameters.extent.depth, pixelAccessData.data());
478 
479         readImage(m_colorAttachment->getImage(), dst);
480 
481         if (!checkImage(dst))
482             return tcu::TestStatus::fail("Fail");
483     }
484 
485     return tcu::TestStatus::pass("Pass");
486 }
487 
beforeRenderPass(void)488 void MultiViewRenderTestInstance::beforeRenderPass(void)
489 {
490     const VkImageSubresourceRange subresourceRange = {
491         VK_IMAGE_ASPECT_COLOR_BIT, //VkImageAspectFlags aspectMask;
492         0u,                        //uint32_t baseMipLevel;
493         1u,                        //uint32_t levelCount;
494         0u,                        //uint32_t baseArrayLayer;
495         m_parameters.extent.depth, //uint32_t layerCount;
496     };
497     imageBarrier(*m_device, *m_cmdBuffer, m_colorAttachment->getImage(), subresourceRange, VK_IMAGE_LAYOUT_UNDEFINED,
498                  VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0, VK_ACCESS_TRANSFER_WRITE_BIT,
499                  VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
500 
501     const VkClearValue renderPassClearValue = makeClearValueColor(tcu::Vec4(0.0f));
502     m_device->cmdClearColorImage(*m_cmdBuffer, m_colorAttachment->getImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
503                                  &renderPassClearValue.color, 1, &subresourceRange);
504 
505     imageBarrier(*m_device, *m_cmdBuffer, m_colorAttachment->getImage(), subresourceRange,
506                  VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
507                  VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
508                  VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
509 }
510 
afterRenderPass(void)511 void MultiViewRenderTestInstance::afterRenderPass(void)
512 {
513     const VkImageSubresourceRange subresourceRange = {
514         VK_IMAGE_ASPECT_COLOR_BIT, //VkImageAspectFlags aspectMask;
515         0u,                        //uint32_t baseMipLevel;
516         1u,                        //uint32_t levelCount;
517         0u,                        //uint32_t baseArrayLayer;
518         m_parameters.extent.depth, //uint32_t layerCount;
519     };
520 
521     imageBarrier(*m_device, *m_cmdBuffer, m_colorAttachment->getImage(), subresourceRange,
522                  VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL,
523                  VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
524                  VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
525 }
526 
527 #ifndef CTS_USES_VULKANSC
addRenderingSubpassDependencyIfRequired(uint32_t currentSubpassNdx)528 void MultiViewRenderTestInstance::addRenderingSubpassDependencyIfRequired(uint32_t currentSubpassNdx)
529 {
530     // Get the combined view mask since the last pipeline barrier.
531     uint32_t viewMask = 0;
532 
533     for (uint32_t subpassNdx = 0; subpassNdx < currentSubpassNdx; ++subpassNdx)
534     {
535         if ((viewMask & m_parameters.viewMasks[subpassNdx]) != 0)
536         {
537             viewMask = 0; // This subpass should have a pipeline barrier so reset the view mask.
538         }
539 
540         viewMask |= m_parameters.viewMasks[subpassNdx];
541     }
542 
543     // Add a pipeline barrier if the view mask for this subpass contains bits used in previous subpasses
544     // since the last pipeline barrier.
545     if ((viewMask & m_parameters.viewMasks[currentSubpassNdx]) != 0)
546     {
547         const VkImageSubresourceRange subresourceRange = {
548             VK_IMAGE_ASPECT_COLOR_BIT, //VkImageAspectFlags aspectMask;
549             0u,                        //uint32_t baseMipLevel;
550             1u,                        //uint32_t levelCount;
551             0u,                        //uint32_t baseArrayLayer;
552             m_parameters.extent.depth, //uint32_t layerCount;
553         };
554 
555         imageBarrier(*m_device, *m_cmdBuffer, m_colorAttachment->getImage(), subresourceRange,
556                      VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
557                      VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
558                      VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
559     }
560 }
561 #endif // CTS_USES_VULKANSC
562 
draw(const uint32_t subpassCount,VkRenderPass renderPass,VkFramebuffer frameBuffer,vector<PipelineSp> & pipelines)563 void MultiViewRenderTestInstance::draw(const uint32_t subpassCount, VkRenderPass renderPass, VkFramebuffer frameBuffer,
564                                        vector<PipelineSp> &pipelines)
565 {
566     const VkRect2D renderArea                = {{0, 0}, {m_parameters.extent.width, m_parameters.extent.height}};
567     const VkClearValue renderPassClearValue  = makeClearValueColor(tcu::Vec4(0.0f));
568     const VkBuffer vertexBuffers[]           = {*m_vertexCoordBuffer, *m_vertexColorBuffer};
569     const VkDeviceSize vertexBufferOffsets[] = {0u, 0u};
570     const uint32_t drawCountPerSubpass       = (subpassCount == 1) ? m_squareCount : 1u;
571 
572     beginCommandBuffer(*m_device, *m_cmdBuffer);
573 
574     beforeRenderPass();
575 
576     if (!m_useDynamicRendering)
577     {
578         const VkRenderPassBeginInfo renderPassBeginInfo{
579             VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
580             DE_NULL,                                  // const void* pNext;
581             renderPass,                               // VkRenderPass renderPass;
582             frameBuffer,                              // VkFramebuffer framebuffer;
583             renderArea,                               // VkRect2D renderArea;
584             1u,                                       // uint32_t clearValueCount;
585             &renderPassClearValue,                    // const VkClearValue* pClearValues;
586         };
587         cmdBeginRenderPass(*m_device, *m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE,
588                            m_parameters.renderingType);
589     }
590 
591     for (uint32_t subpassNdx = 0u; subpassNdx < subpassCount; subpassNdx++)
592     {
593         m_device->cmdBindVertexBuffers(*m_cmdBuffer, 0u, DE_LENGTH_OF_ARRAY(vertexBuffers), vertexBuffers,
594                                        vertexBufferOffsets);
595 
596         if (m_parameters.viewIndex == TEST_TYPE_DRAW_INDEXED)
597             m_device->cmdBindIndexBuffer(*m_cmdBuffer, *m_vertexIndicesBuffer, 0u, VK_INDEX_TYPE_UINT32);
598 
599         bindResources();
600 
601 #ifndef CTS_USES_VULKANSC
602         if (m_useDynamicRendering)
603         {
604             addRenderingSubpassDependencyIfRequired(subpassNdx);
605 
606             beginRendering(*m_device, *m_cmdBuffer, m_colorAttachment->getImageView(), renderArea, renderPassClearValue,
607                            VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
608                            (subpassNdx ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_CLEAR), 0u,
609                            m_parameters.extent.depth, m_parameters.viewMasks[subpassNdx]);
610         }
611 #endif // CTS_USES_VULKANSC
612 
613         m_device->cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipelines[subpassNdx]);
614 
615         for (uint32_t drawNdx = 0u; drawNdx < drawCountPerSubpass; ++drawNdx)
616             if (m_parameters.viewIndex == TEST_TYPE_DRAW_INDEXED)
617                 m_device->cmdDrawIndexed(*m_cmdBuffer, 4u, 1u, (drawNdx + subpassNdx % m_squareCount) * 4u, 0u, 0u);
618             else
619                 m_device->cmdDraw(*m_cmdBuffer, 4u, 1u, (drawNdx + subpassNdx % m_squareCount) * 4u, 0u);
620 
621 #ifndef CTS_USES_VULKANSC
622         if (m_useDynamicRendering)
623             endRendering(*m_device, *m_cmdBuffer);
624         else
625 #endif // CTS_USES_VULKANSC
626             if (subpassNdx < subpassCount - 1u)
627                 cmdNextSubpass(*m_device, *m_cmdBuffer, VK_SUBPASS_CONTENTS_INLINE, m_parameters.renderingType);
628     }
629 
630     if (!m_useDynamicRendering)
631         cmdEndRenderPass(*m_device, *m_cmdBuffer, m_parameters.renderingType);
632 
633     afterRenderPass();
634 
635     VK_CHECK(m_device->endCommandBuffer(*m_cmdBuffer));
636     submitCommandsAndWait(*m_device, *m_logicalDevice, m_queue, *m_cmdBuffer);
637 }
638 
createVertexData(void)639 void MultiViewRenderTestInstance::createVertexData(void)
640 {
641     tcu::Vec4 color = tcu::Vec4(0.2f, 0.0f, 0.1f, 1.0f);
642 
643     appendVertex(tcu::Vec4(-1.0f, -1.0f, 1.0f, 1.0f), color);
644     appendVertex(tcu::Vec4(-1.0f, 0.0f, 1.0f, 1.0f), color);
645     appendVertex(tcu::Vec4(0.0f, -1.0f, 1.0f, 1.0f), color);
646     appendVertex(tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), color);
647 
648     color = tcu::Vec4(0.3f, 0.0f, 0.2f, 1.0f);
649     appendVertex(tcu::Vec4(-1.0f, 0.0f, 1.0f, 1.0f), color);
650     appendVertex(tcu::Vec4(-1.0f, 1.0f, 1.0f, 1.0f), color);
651     appendVertex(tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), color);
652     appendVertex(tcu::Vec4(0.0f, 1.0f, 1.0f, 1.0f), color);
653 
654     color = tcu::Vec4(0.4f, 0.2f, 0.3f, 1.0f);
655     appendVertex(tcu::Vec4(0.0f, -1.0f, 1.0f, 1.0f), color);
656     appendVertex(tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), color);
657     appendVertex(tcu::Vec4(1.0f, -1.0f, 1.0f, 1.0f), color);
658     appendVertex(tcu::Vec4(1.0f, 0.0f, 1.0f, 1.0f), color);
659 
660     color = tcu::Vec4(0.5f, 0.0f, 0.4f, 1.0f);
661     appendVertex(tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), color);
662     appendVertex(tcu::Vec4(0.0f, 1.0f, 1.0f, 1.0f), color);
663     appendVertex(tcu::Vec4(1.0f, 0.0f, 1.0f, 1.0f), color);
664     appendVertex(tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f), color);
665 
666     if (m_parameters.viewIndex == TEST_TYPE_DRAW_INDEXED || m_parameters.viewIndex == TEST_TYPE_DRAW_INDIRECT_INDEXED)
667     {
668         const size_t verticesCount = m_vertexCoord.size();
669         vector<tcu::Vec4> vertexColor(verticesCount);
670         vector<tcu::Vec4> vertexCoord(verticesCount);
671 
672         m_vertexIndices.clear();
673         m_vertexIndices.reserve(verticesCount);
674         for (uint32_t vertexIdx = 0; vertexIdx < verticesCount; ++vertexIdx)
675             m_vertexIndices.push_back(vertexIdx);
676 
677         de::Random(m_seed).shuffle(m_vertexIndices.begin(), m_vertexIndices.end());
678 
679         for (uint32_t vertexIdx = 0; vertexIdx < verticesCount; ++vertexIdx)
680             vertexColor[m_vertexIndices[vertexIdx]] = m_vertexColor[vertexIdx];
681         m_vertexColor.assign(vertexColor.begin(), vertexColor.end());
682 
683         for (uint32_t vertexIdx = 0; vertexIdx < verticesCount; ++vertexIdx)
684             vertexCoord[m_vertexIndices[vertexIdx]] = m_vertexCoord[vertexIdx];
685         m_vertexCoord.assign(vertexCoord.begin(), vertexCoord.end());
686     }
687 }
688 
fillMissingParameters(const TestParameters & parameters)689 TestParameters MultiViewRenderTestInstance::fillMissingParameters(const TestParameters &parameters)
690 {
691     if (!parameters.viewMasks.empty())
692         return parameters;
693     else
694     {
695         const auto &instanceDriver = m_context.getInstanceInterface();
696         const auto physicalDevice  = m_context.getPhysicalDevice();
697 
698         VkPhysicalDeviceMultiviewProperties multiviewProperties = {
699             VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES, // VkStructureType sType;
700             DE_NULL,                                                // void* pNext;
701             0u,                                                     // uint32_t maxMultiviewViewCount;
702             0u                                                      // uint32_t maxMultiviewInstanceIndex;
703         };
704 
705         VkPhysicalDeviceProperties2 deviceProperties2;
706         deviceProperties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
707         deviceProperties2.pNext = &multiviewProperties;
708 
709         instanceDriver.getPhysicalDeviceProperties2(physicalDevice, &deviceProperties2);
710 
711         TestParameters newParameters = parameters;
712         newParameters.extent.depth   = multiviewProperties.maxMultiviewViewCount;
713 
714         vector<uint32_t> viewMasks(multiviewProperties.maxMultiviewViewCount);
715         for (uint32_t i = 0; i < multiviewProperties.maxMultiviewViewCount; i++)
716             viewMasks[i] = 1 << i;
717         newParameters.viewMasks = viewMasks;
718 
719         return newParameters;
720     }
721 }
722 
createVertexBuffer(void)723 void MultiViewRenderTestInstance::createVertexBuffer(void)
724 {
725     DE_ASSERT(m_vertexCoord.size() == m_vertexColor.size());
726     DE_ASSERT(m_vertexCoord.size() != 0);
727 
728     const size_t nonCoherentAtomSize = static_cast<size_t>(m_context.getDeviceProperties().limits.nonCoherentAtomSize);
729 
730     // Upload vertex coordinates
731     {
732         const size_t dataSize               = static_cast<size_t>(m_vertexCoord.size() * sizeof(m_vertexCoord[0]));
733         const VkDeviceSize bufferDataSize   = static_cast<VkDeviceSize>(deAlignSize(dataSize, nonCoherentAtomSize));
734         const VkBufferCreateInfo bufferInfo = makeBufferCreateInfo(bufferDataSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
735 
736         m_vertexCoordBuffer = createBuffer(*m_device, *m_logicalDevice, &bufferInfo);
737         m_vertexCoordAlloc =
738             m_allocator->allocate(getBufferMemoryRequirements(*m_device, *m_logicalDevice, *m_vertexCoordBuffer),
739                                   MemoryRequirement::HostVisible);
740 
741         VK_CHECK(m_device->bindBufferMemory(*m_logicalDevice, *m_vertexCoordBuffer, m_vertexCoordAlloc->getMemory(),
742                                             m_vertexCoordAlloc->getOffset()));
743         deMemcpy(m_vertexCoordAlloc->getHostPtr(), m_vertexCoord.data(), static_cast<size_t>(dataSize));
744         flushAlloc(*m_device, *m_logicalDevice, *m_vertexCoordAlloc);
745     }
746 
747     // Upload vertex colors
748     {
749         const size_t dataSize               = static_cast<size_t>(m_vertexColor.size() * sizeof(m_vertexColor[0]));
750         const VkDeviceSize bufferDataSize   = static_cast<VkDeviceSize>(deAlignSize(dataSize, nonCoherentAtomSize));
751         const VkBufferCreateInfo bufferInfo = makeBufferCreateInfo(bufferDataSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
752 
753         m_vertexColorBuffer = createBuffer(*m_device, *m_logicalDevice, &bufferInfo);
754         m_vertexColorAlloc =
755             m_allocator->allocate(getBufferMemoryRequirements(*m_device, *m_logicalDevice, *m_vertexColorBuffer),
756                                   MemoryRequirement::HostVisible);
757 
758         VK_CHECK(m_device->bindBufferMemory(*m_logicalDevice, *m_vertexColorBuffer, m_vertexColorAlloc->getMemory(),
759                                             m_vertexColorAlloc->getOffset()));
760         deMemcpy(m_vertexColorAlloc->getHostPtr(), m_vertexColor.data(), static_cast<size_t>(dataSize));
761         flushAlloc(*m_device, *m_logicalDevice, *m_vertexColorAlloc);
762     }
763 
764     // Upload vertex indices
765     if (m_parameters.viewIndex == TEST_TYPE_DRAW_INDEXED || m_parameters.viewIndex == TEST_TYPE_DRAW_INDIRECT_INDEXED)
766     {
767         const size_t dataSize               = static_cast<size_t>(m_vertexIndices.size() * sizeof(m_vertexIndices[0]));
768         const VkDeviceSize bufferDataSize   = static_cast<VkDeviceSize>(deAlignSize(dataSize, nonCoherentAtomSize));
769         const VkBufferCreateInfo bufferInfo = makeBufferCreateInfo(bufferDataSize, VK_BUFFER_USAGE_INDEX_BUFFER_BIT);
770 
771         DE_ASSERT(m_vertexIndices.size() == m_vertexCoord.size());
772 
773         m_vertexIndicesBuffer = createBuffer(*m_device, *m_logicalDevice, &bufferInfo);
774         m_vertexIndicesAllocation =
775             m_allocator->allocate(getBufferMemoryRequirements(*m_device, *m_logicalDevice, *m_vertexIndicesBuffer),
776                                   MemoryRequirement::HostVisible);
777 
778         // Init host buffer data
779         VK_CHECK(m_device->bindBufferMemory(*m_logicalDevice, *m_vertexIndicesBuffer,
780                                             m_vertexIndicesAllocation->getMemory(),
781                                             m_vertexIndicesAllocation->getOffset()));
782         deMemcpy(m_vertexIndicesAllocation->getHostPtr(), m_vertexIndices.data(), static_cast<size_t>(dataSize));
783         flushAlloc(*m_device, *m_logicalDevice, *m_vertexIndicesAllocation);
784     }
785     else
786         DE_ASSERT(m_vertexIndices.empty());
787 }
788 
createMultiViewDevices(void)789 void MultiViewRenderTestInstance::createMultiViewDevices(void)
790 {
791     const auto &instanceDriver            = m_context.getInstanceInterface();
792     const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
793     const vector<VkQueueFamilyProperties> queueFamilyProperties =
794         getPhysicalDeviceQueueFamilyProperties(instanceDriver, physicalDevice);
795 
796     for (; m_queueFamilyIndex < queueFamilyProperties.size(); ++m_queueFamilyIndex)
797     {
798         if ((queueFamilyProperties[m_queueFamilyIndex].queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0)
799             break;
800     }
801 
802     const float queuePriorities             = 1.0f;
803     const VkDeviceQueueCreateInfo queueInfo = {
804         VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, //VkStructureType sType;
805         DE_NULL,                                    //const void* pNext;
806         (VkDeviceQueueCreateFlags)0u,               //VkDeviceQueueCreateFlags flags;
807         m_queueFamilyIndex,                         //uint32_t queueFamilyIndex;
808         1u,                                         //uint32_t queueCount;
809         &queuePriorities                            //const float* pQueuePriorities;
810     };
811 
812 #ifndef CTS_USES_VULKANSC
813     VkPhysicalDeviceDynamicRenderingFeatures dynamicRenderingFeatures = {
814         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES, // VkStructureType sType;
815         DE_NULL,                                                      // void* pNext;
816         false,                                                        // VkBool32                    dynamicRendering
817     };
818 #endif // CTS_USES_VULKANSC
819 
820     VkPhysicalDeviceMultiviewFeatures multiviewFeatures = {
821         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES, // VkStructureType sType;
822 #ifndef CTS_USES_VULKANSC
823         &dynamicRenderingFeatures, // void* pNext;
824 #else
825         DE_NULL, // void* pNext;
826 #endif         // CTS_USES_VULKANSC
827         false, // VkBool32 multiview;
828         false, // VkBool32 multiviewGeometryShader;
829         false, // VkBool32 multiviewTessellationShader;
830     };
831 
832     VkPhysicalDeviceFeatures2 enabledFeatures;
833     enabledFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
834     enabledFeatures.pNext = &multiviewFeatures;
835 
836 #ifndef CTS_USES_VULKANSC
837     VkPhysicalDeviceNestedCommandBufferFeaturesEXT nestedCommandBufferFeatures = vk::initVulkanStructure();
838     if (m_parameters.viewIndex == TEST_TYPE_NESTED_CMD_BUFFER)
839     {
840         nestedCommandBufferFeatures.pNext = enabledFeatures.pNext;
841         enabledFeatures.pNext             = &nestedCommandBufferFeatures;
842     }
843 #endif
844 
845     instanceDriver.getPhysicalDeviceFeatures2(physicalDevice, &enabledFeatures);
846 
847     if (!multiviewFeatures.multiview)
848         TCU_THROW(NotSupportedError, "MultiView not supported");
849 
850     if (m_parameters.geometryShaderNeeded() && !multiviewFeatures.multiviewGeometryShader)
851         TCU_THROW(NotSupportedError, "Geometry shader is not supported");
852 
853     if (TEST_TYPE_VIEW_INDEX_IN_TESELLATION == m_parameters.viewIndex && !multiviewFeatures.multiviewTessellationShader)
854         TCU_THROW(NotSupportedError, "Tessellation shader is not supported");
855 
856     VkPhysicalDeviceMultiviewProperties multiviewProperties = {
857         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES, //VkStructureType sType;
858         DE_NULL,                                                //void* pNext;
859         0u,                                                     //uint32_t maxMultiviewViewCount;
860         0u                                                      //uint32_t maxMultiviewInstanceIndex;
861     };
862 
863     VkPhysicalDeviceProperties2 propertiesDeviceProperties2;
864     propertiesDeviceProperties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
865     propertiesDeviceProperties2.pNext = &multiviewProperties;
866 
867     instanceDriver.getPhysicalDeviceProperties2(physicalDevice, &propertiesDeviceProperties2);
868 
869 #ifndef CTS_USES_VULKANSC
870     if (multiviewProperties.maxMultiviewViewCount < 6u)
871         TCU_FAIL("maxMultiviewViewCount below min value");
872 #endif // CTS_USES_VULKANSC
873 
874     if (multiviewProperties.maxMultiviewInstanceIndex < 134217727u) //134217727u = 2^27 -1
875         TCU_FAIL("maxMultiviewInstanceIndex below min value");
876 
877     if (multiviewProperties.maxMultiviewViewCount < m_parameters.extent.depth)
878         TCU_THROW(NotSupportedError, "Limit MaxMultiviewViewCount to small to run this test");
879 
880     m_hasMultiDrawIndirect = enabledFeatures.features.multiDrawIndirect;
881 
882     {
883         vector<const char *> deviceExtensions;
884 
885         if (!isCoreDeviceExtension(m_context.getUsedApiVersion(), "VK_KHR_multiview"))
886             deviceExtensions.push_back("VK_KHR_multiview");
887 
888         if ((m_parameters.renderingType == RENDERING_TYPE_RENDERPASS2) &&
889             !isCoreDeviceExtension(m_context.getUsedApiVersion(), "VK_KHR_create_renderpass2"))
890             deviceExtensions.push_back("VK_KHR_create_renderpass2");
891         if ((m_parameters.renderingType == RENDERING_TYPE_DYNAMIC_RENDERING) &&
892             !isCoreDeviceExtension(m_context.getUsedApiVersion(), "VK_KHR_dynamic_rendering"))
893             deviceExtensions.push_back("VK_KHR_dynamic_rendering");
894 
895         if (m_parameters.viewIndex == TEST_TYPE_DEPTH_DIFFERENT_RANGES)
896             deviceExtensions.push_back("VK_EXT_depth_range_unrestricted");
897 
898         if (m_parameters.viewIndex == TEST_TYPE_NESTED_CMD_BUFFER)
899             deviceExtensions.push_back("VK_EXT_nested_command_buffer");
900 
901         void *pNext = &enabledFeatures;
902 #ifdef CTS_USES_VULKANSC
903         VkDeviceObjectReservationCreateInfo memReservationInfo =
904             m_context.getTestContext().getCommandLine().isSubProcess() ?
905                 m_context.getResourceInterface()->getStatMax() :
906                 resetDeviceObjectReservationCreateInfo();
907         memReservationInfo.pNext = pNext;
908         pNext                    = &memReservationInfo;
909 
910         VkPhysicalDeviceVulkanSC10Features sc10Features = createDefaultSC10Features();
911         sc10Features.pNext                              = pNext;
912         pNext                                           = &sc10Features;
913 
914         VkPipelineCacheCreateInfo pcCI;
915         std::vector<VkPipelinePoolSize> poolSizes;
916         if (m_context.getTestContext().getCommandLine().isSubProcess())
917         {
918             if (m_context.getResourceInterface()->getCacheDataSize() > 0)
919             {
920                 pcCI = {
921                     VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO, // VkStructureType sType;
922                     DE_NULL,                                      // const void* pNext;
923                     VK_PIPELINE_CACHE_CREATE_READ_ONLY_BIT |
924                         VK_PIPELINE_CACHE_CREATE_USE_APPLICATION_STORAGE_BIT, // VkPipelineCacheCreateFlags flags;
925                     m_context.getResourceInterface()->getCacheDataSize(),     // uintptr_t initialDataSize;
926                     m_context.getResourceInterface()->getCacheData()          // const void* pInitialData;
927                 };
928                 memReservationInfo.pipelineCacheCreateInfoCount = 1;
929                 memReservationInfo.pPipelineCacheCreateInfos    = &pcCI;
930             }
931 
932             poolSizes = m_context.getResourceInterface()->getPipelinePoolSizes();
933             if (!poolSizes.empty())
934             {
935                 memReservationInfo.pipelinePoolSizeCount = uint32_t(poolSizes.size());
936                 memReservationInfo.pPipelinePoolSizes    = poolSizes.data();
937             }
938         }
939 #endif // CTS_USES_VULKANSC
940 
941         const VkDeviceCreateInfo deviceInfo = {
942             VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,           //VkStructureType sType;
943             pNext,                                          //const void* pNext;
944             0u,                                             //VkDeviceCreateFlags flags;
945             1u,                                             //uint32_t queueCreateInfoCount;
946             &queueInfo,                                     //const VkDeviceQueueCreateInfo* pQueueCreateInfos;
947             0u,                                             //uint32_t enabledLayerCount;
948             DE_NULL,                                        //const char* const* ppEnabledLayerNames;
949             static_cast<uint32_t>(deviceExtensions.size()), //uint32_t enabledExtensionCount;
950             deviceExtensions.empty() ? DE_NULL : &deviceExtensions[0], //const char* const* pEnabledExtensionNames;
951             DE_NULL //const VkPhysicalDeviceFeatures* pEnabledFeatures;
952         };
953 
954         const auto instance = m_context.getInstance();
955 
956         m_logicalDevice =
957             createCustomDevice(m_context.getTestContext().getCommandLine().isValidationEnabled(),
958                                m_context.getPlatformInterface(), instance, instanceDriver, physicalDevice, &deviceInfo);
959 #ifndef CTS_USES_VULKANSC
960         m_device = de::MovePtr<DeviceDriver>(new DeviceDriver(m_context.getPlatformInterface(), instance,
961                                                               *m_logicalDevice, m_context.getUsedApiVersion(),
962                                                               m_context.getTestContext().getCommandLine()));
963 #else
964         m_device = de::MovePtr<DeviceDriverSC, DeinitDeviceDeleter>(
965             new DeviceDriverSC(m_context.getPlatformInterface(), instance, *m_logicalDevice,
966                                m_context.getTestContext().getCommandLine(), m_context.getResourceInterface(),
967                                m_context.getDeviceVulkanSC10Properties(), m_context.getDeviceProperties(),
968                                m_context.getUsedApiVersion()),
969             vk::DeinitDeviceDeleter(m_context.getResourceInterface().get(), *m_logicalDevice));
970 #endif // CTS_USES_VULKANSC
971         m_allocator = MovePtr<Allocator>(new SimpleAllocator(
972             *m_device, *m_logicalDevice, getPhysicalDeviceMemoryProperties(instanceDriver, physicalDevice)));
973         m_device->getDeviceQueue(*m_logicalDevice, m_queueFamilyIndex, 0u, &m_queue);
974     }
975 }
976 
createCommandBuffer(void)977 void MultiViewRenderTestInstance::createCommandBuffer(void)
978 {
979     // cmdPool
980     {
981         const VkCommandPoolCreateInfo cmdPoolParams = {
982             VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,      // VkStructureType sType;
983             DE_NULL,                                         // const void* pNext;
984             VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // VkCmdPoolCreateFlags flags;
985             m_queueFamilyIndex,                              // uint32_t queueFamilyIndex;
986         };
987         m_cmdPool = createCommandPool(*m_device, *m_logicalDevice, &cmdPoolParams);
988     }
989 
990     // cmdBuffer
991     {
992         const VkCommandBufferAllocateInfo cmdBufferAllocateInfo = {
993             VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
994             DE_NULL,                                        // const void* pNext;
995             *m_cmdPool,                                     // VkCommandPool commandPool;
996             VK_COMMAND_BUFFER_LEVEL_PRIMARY,                // VkCommandBufferLevel level;
997             1u,                                             // uint32_t bufferCount;
998         };
999         m_cmdBuffer = allocateCommandBuffer(*m_device, *m_logicalDevice, &cmdBufferAllocateInfo);
1000     }
1001 }
1002 
createSecondaryCommandPool(void)1003 void MultiViewRenderTestInstance::createSecondaryCommandPool(void)
1004 {
1005     // cmdPool
1006     {
1007         const VkCommandPoolCreateInfo cmdPoolParams = {
1008             VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,      // VkStructureType sType;
1009             DE_NULL,                                         // const void* pNext;
1010             VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // VkCmdPoolCreateFlags flags;
1011             m_queueFamilyIndex,                              // uint32_t queueFamilyIndex;
1012         };
1013         m_cmdPoolSecondary = createCommandPool(*m_device, *m_logicalDevice, &cmdPoolParams);
1014     }
1015 }
1016 
madeShaderModule(map<VkShaderStageFlagBits,ShaderModuleSP> & shaderModule,vector<VkPipelineShaderStageCreateInfo> & shaderStageParams)1017 void MultiViewRenderTestInstance::madeShaderModule(map<VkShaderStageFlagBits, ShaderModuleSP> &shaderModule,
1018                                                    vector<VkPipelineShaderStageCreateInfo> &shaderStageParams)
1019 {
1020     // create shaders modules
1021     switch (m_parameters.viewIndex)
1022     {
1023     case TEST_TYPE_VIEW_MASK:
1024     case TEST_TYPE_VIEW_INDEX_IN_VERTEX:
1025     case TEST_TYPE_VIEW_INDEX_IN_FRAGMENT:
1026     case TEST_TYPE_INSTANCED_RENDERING:
1027     case TEST_TYPE_INPUT_RATE_INSTANCE:
1028     case TEST_TYPE_DRAW_INDIRECT:
1029     case TEST_TYPE_DRAW_INDIRECT_INDEXED:
1030     case TEST_TYPE_DRAW_INDEXED:
1031     case TEST_TYPE_CLEAR_ATTACHMENTS:
1032     case TEST_TYPE_SECONDARY_CMD_BUFFER:
1033     case TEST_TYPE_INPUT_ATTACHMENTS:
1034     case TEST_TYPE_POINT_SIZE:
1035     case TEST_TYPE_MULTISAMPLE:
1036     case TEST_TYPE_QUERIES:
1037     case TEST_TYPE_NON_PRECISE_QUERIES:
1038     case TEST_TYPE_NON_PRECISE_QUERIES_WITH_AVAILABILITY:
1039     case TEST_TYPE_READBACK_WITH_IMPLICIT_CLEAR:
1040     case TEST_TYPE_READBACK_WITH_EXPLICIT_CLEAR:
1041     case TEST_TYPE_DEPTH:
1042     case TEST_TYPE_DEPTH_DIFFERENT_RANGES:
1043     case TEST_TYPE_STENCIL:
1044     case TEST_TYPE_NESTED_CMD_BUFFER:
1045         shaderModule[VK_SHADER_STAGE_VERTEX_BIT]   = (ShaderModuleSP(new Unique<VkShaderModule>(
1046             createShaderModule(*m_device, *m_logicalDevice, m_context.getBinaryCollection().get("vertex"), 0))));
1047         shaderModule[VK_SHADER_STAGE_FRAGMENT_BIT] = (ShaderModuleSP(new Unique<VkShaderModule>(
1048             createShaderModule(*m_device, *m_logicalDevice, m_context.getBinaryCollection().get("fragment"), 0))));
1049         break;
1050     case TEST_TYPE_VIEW_INDEX_IN_GEOMETRY:
1051     case TEST_TYPE_INPUT_ATTACHMENTS_GEOMETRY:
1052     case TEST_TYPE_SECONDARY_CMD_BUFFER_GEOMETRY:
1053         shaderModule[VK_SHADER_STAGE_VERTEX_BIT]   = (ShaderModuleSP(new Unique<VkShaderModule>(
1054             createShaderModule(*m_device, *m_logicalDevice, m_context.getBinaryCollection().get("vertex"), 0))));
1055         shaderModule[VK_SHADER_STAGE_GEOMETRY_BIT] = (ShaderModuleSP(new Unique<VkShaderModule>(
1056             createShaderModule(*m_device, *m_logicalDevice, m_context.getBinaryCollection().get("geometry"), 0))));
1057         shaderModule[VK_SHADER_STAGE_FRAGMENT_BIT] = (ShaderModuleSP(new Unique<VkShaderModule>(
1058             createShaderModule(*m_device, *m_logicalDevice, m_context.getBinaryCollection().get("fragment"), 0))));
1059         break;
1060     case TEST_TYPE_VIEW_INDEX_IN_TESELLATION:
1061         shaderModule[VK_SHADER_STAGE_VERTEX_BIT] = (ShaderModuleSP(new Unique<VkShaderModule>(
1062             createShaderModule(*m_device, *m_logicalDevice, m_context.getBinaryCollection().get("vertex"), 0))));
1063         shaderModule[VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT] =
1064             (ShaderModuleSP(new Unique<VkShaderModule>(createShaderModule(
1065                 *m_device, *m_logicalDevice, m_context.getBinaryCollection().get("tessellation_control"), 0))));
1066         shaderModule[VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT] =
1067             (ShaderModuleSP(new Unique<VkShaderModule>(createShaderModule(
1068                 *m_device, *m_logicalDevice, m_context.getBinaryCollection().get("tessellation_evaluation"), 0))));
1069         shaderModule[VK_SHADER_STAGE_FRAGMENT_BIT] = (ShaderModuleSP(new Unique<VkShaderModule>(
1070             createShaderModule(*m_device, *m_logicalDevice, m_context.getBinaryCollection().get("fragment"), 0))));
1071         break;
1072     case TEST_TYPE_VIEW_MASK_ITERATION:
1073     {
1074         const auto vk12Support                     = m_context.contextSupports(vk::ApiVersion(0u, 1u, 2u, 0u));
1075         const auto vertShaderName                  = vk12Support ? "vert-spv15" : "vert-spv10";
1076         shaderModule[VK_SHADER_STAGE_VERTEX_BIT]   = (ShaderModuleSP(new Unique<VkShaderModule>(
1077             createShaderModule(*m_device, *m_logicalDevice, m_context.getBinaryCollection().get(vertShaderName), 0))));
1078         shaderModule[VK_SHADER_STAGE_FRAGMENT_BIT] = (ShaderModuleSP(new Unique<VkShaderModule>(createShaderModule(
1079             *m_device, *m_logicalDevice, m_context.getBinaryCollection().get("view_mask_iteration"), 0))));
1080         break;
1081     }
1082     default:
1083         DE_ASSERT(0);
1084         break;
1085     }
1086 
1087     VkPipelineShaderStageCreateInfo pipelineShaderStage = {
1088         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
1089         DE_NULL,                                             // const void* pNext;
1090         (VkPipelineShaderStageCreateFlags)0,                 // VkPipelineShaderStageCreateFlags flags;
1091         (VkShaderStageFlagBits)0,                            // VkShaderStageFlagBits stage;
1092         (VkShaderModule)0,                                   // VkShaderModule module;
1093         "main",                                              // const char* pName;
1094         (const VkSpecializationInfo *)DE_NULL,               // const VkSpecializationInfo* pSpecializationInfo;
1095     };
1096 
1097     for (map<VkShaderStageFlagBits, ShaderModuleSP>::iterator it = shaderModule.begin(); it != shaderModule.end(); ++it)
1098     {
1099         pipelineShaderStage.stage  = it->first;
1100         pipelineShaderStage.module = **it->second;
1101         shaderStageParams.push_back(pipelineShaderStage);
1102     }
1103 }
1104 
makeGraphicsPipeline(const VkRenderPass renderPass,const VkPipelineLayout pipelineLayout,const uint32_t pipelineShaderStageCount,const VkPipelineShaderStageCreateInfo * pipelineShaderStageCreate,const uint32_t subpass,const VkVertexInputRate vertexInputRate,const bool useDepthTest,const bool useStencilTest,const float minDepth,const float maxDepth,const VkFormat dsFormat)1105 Move<VkPipeline> MultiViewRenderTestInstance::makeGraphicsPipeline(
1106     const VkRenderPass renderPass, const VkPipelineLayout pipelineLayout, const uint32_t pipelineShaderStageCount,
1107     const VkPipelineShaderStageCreateInfo *pipelineShaderStageCreate, const uint32_t subpass,
1108     const VkVertexInputRate vertexInputRate, const bool useDepthTest, const bool useStencilTest, const float minDepth,
1109     const float maxDepth, const VkFormat dsFormat)
1110 {
1111     const VkVertexInputBindingDescription vertexInputBindingDescriptions[] = {
1112         {
1113             0u,                                              // binding;
1114             static_cast<uint32_t>(sizeof(m_vertexCoord[0])), // stride;
1115             vertexInputRate                                  // inputRate
1116         },
1117         {
1118             1u,                                              // binding;
1119             static_cast<uint32_t>(sizeof(m_vertexColor[0])), // stride;
1120             vertexInputRate                                  // inputRate
1121         }};
1122 
1123     const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] = {
1124         {
1125             0u,                            // uint32_t location;
1126             0u,                            // uint32_t binding;
1127             VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
1128             0u                             // uint32_t offset;
1129         },                                 // VertexElementData::position
1130         {
1131             1u,                            // uint32_t location;
1132             1u,                            // uint32_t binding;
1133             VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
1134             0u                             // uint32_t offset;
1135         },                                 // VertexElementData::color
1136     };
1137 
1138     const VkPipelineVertexInputStateCreateInfo vertexInputStateParams = {
1139         VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
1140         NULL,                                                      // const void* pNext;
1141         0u,                                                        // VkPipelineVertexInputStateCreateFlags flags;
1142         DE_LENGTH_OF_ARRAY(vertexInputBindingDescriptions),        // uint32_t vertexBindingDescriptionCount;
1143         vertexInputBindingDescriptions, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
1144         DE_LENGTH_OF_ARRAY(vertexInputAttributeDescriptions), // uint32_t vertexAttributeDescriptionCount;
1145         vertexInputAttributeDescriptions // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
1146     };
1147 
1148     const VkPrimitiveTopology topology =
1149         (TEST_TYPE_VIEW_INDEX_IN_TESELLATION == m_parameters.viewIndex) ? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST :
1150         (TEST_TYPE_POINT_SIZE == m_parameters.viewIndex)                ? VK_PRIMITIVE_TOPOLOGY_POINT_LIST :
1151                                                                           VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
1152 
1153     const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateParams = {
1154         VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
1155         DE_NULL,                                                     // const void* pNext;
1156         0u,                                                          // VkPipelineInputAssemblyStateCreateFlags flags;
1157         topology,                                                    // VkPrimitiveTopology topology;
1158         VK_FALSE,                                                    // VkBool32 primitiveRestartEnable;
1159     };
1160 
1161     const VkViewport viewport = makeViewport(0.0f, 0.0f, (float)m_parameters.extent.width,
1162                                              (float)m_parameters.extent.height, minDepth, maxDepth);
1163     const VkRect2D scissor    = makeRect2D(m_parameters.extent);
1164 
1165     const VkPipelineViewportStateCreateInfo viewportStateParams = {
1166         VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
1167         DE_NULL,                                               // const void* pNext;
1168         0u,                                                    // VkPipelineViewportStateCreateFlags flags;
1169         1u,                                                    // uint32_t viewportCount;
1170         &viewport,                                             // const VkViewport* pViewports;
1171         1u,                                                    // uint32_t scissorCount;
1172         &scissor                                               // const VkRect2D* pScissors;
1173     };
1174 
1175     const VkPipelineRasterizationStateCreateInfo rasterStateParams = {
1176         VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
1177         DE_NULL,                                                    // const void* pNext;
1178         0u,                                                         // VkPipelineRasterizationStateCreateFlags flags;
1179         VK_FALSE,                                                   // VkBool32 depthClampEnable;
1180         VK_FALSE,                                                   // VkBool32 rasterizerDiscardEnable;
1181         VK_POLYGON_MODE_FILL,                                       // VkPolygonMode polygonMode;
1182         VK_CULL_MODE_NONE,                                          // VkCullModeFlags cullMode;
1183         VK_FRONT_FACE_COUNTER_CLOCKWISE,                            // VkFrontFace frontFace;
1184         VK_FALSE,                                                   // VkBool32 depthBiasEnable;
1185         0.0f,                                                       // float depthBiasConstantFactor;
1186         0.0f,                                                       // float depthBiasClamp;
1187         0.0f,                                                       // float depthBiasSlopeFactor;
1188         1.0f,                                                       // float lineWidth;
1189     };
1190 
1191     const VkSampleCountFlagBits sampleCountFlagBits =
1192         (TEST_TYPE_MULTISAMPLE == m_parameters.viewIndex) ? VK_SAMPLE_COUNT_4_BIT : VK_SAMPLE_COUNT_1_BIT;
1193     const VkPipelineMultisampleStateCreateInfo multisampleStateParams = {
1194         VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
1195         DE_NULL,                                                  // const void* pNext;
1196         0u,                                                       // VkPipelineMultisampleStateCreateFlags flags;
1197         sampleCountFlagBits,                                      // VkSampleCountFlagBits rasterizationSamples;
1198         VK_FALSE,                                                 // VkBool32 sampleShadingEnable;
1199         0.0f,                                                     // float minSampleShading;
1200         DE_NULL,                                                  // const VkSampleMask* pSampleMask;
1201         VK_FALSE,                                                 // VkBool32 alphaToCoverageEnable;
1202         VK_FALSE,                                                 // VkBool32 alphaToOneEnable;
1203     };
1204 
1205     VkPipelineDepthStencilStateCreateInfo depthStencilStateParams = {
1206         VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
1207         DE_NULL,                                                    // const void* pNext;
1208         0u,                                                         // VkPipelineDepthStencilStateCreateFlags flags;
1209         useDepthTest ? VK_TRUE : VK_FALSE,                          // VkBool32 depthTestEnable;
1210         useDepthTest ? VK_TRUE : VK_FALSE,                          // VkBool32 depthWriteEnable;
1211         VK_COMPARE_OP_LESS_OR_EQUAL,                                // VkCompareOp depthCompareOp;
1212         VK_FALSE,                                                   // VkBool32 depthBoundsTestEnable;
1213         useStencilTest ? VK_TRUE : VK_FALSE,                        // VkBool32 stencilTestEnable;
1214         // VkStencilOpState front;
1215         {
1216             VK_STENCIL_OP_KEEP,                // VkStencilOp failOp;
1217             VK_STENCIL_OP_INCREMENT_AND_CLAMP, // VkStencilOp passOp;
1218             VK_STENCIL_OP_KEEP,                // VkStencilOp depthFailOp;
1219             VK_COMPARE_OP_ALWAYS,              // VkCompareOp compareOp;
1220             ~0u,                               // uint32_t compareMask;
1221             ~0u,                               // uint32_t writeMask;
1222             0u,                                // uint32_t reference;
1223         },
1224         // VkStencilOpState back;
1225         {
1226             VK_STENCIL_OP_KEEP,                // VkStencilOp failOp;
1227             VK_STENCIL_OP_INCREMENT_AND_CLAMP, // VkStencilOp passOp;
1228             VK_STENCIL_OP_KEEP,                // VkStencilOp depthFailOp;
1229             VK_COMPARE_OP_ALWAYS,              // VkCompareOp compareOp;
1230             ~0u,                               // uint32_t compareMask;
1231             ~0u,                               // uint32_t writeMask;
1232             0u,                                // uint32_t reference;
1233         },
1234         0.0f, // float minDepthBounds;
1235         1.0f, // float maxDepthBounds;
1236     };
1237 
1238     const VkPipelineColorBlendAttachmentState colorBlendAttachmentState = {
1239         VK_FALSE,                            // VkBool32 blendEnable;
1240         VK_BLEND_FACTOR_SRC_ALPHA,           // VkBlendFactor srcColorBlendFactor;
1241         VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, // VkBlendFactor dstColorBlendFactor;
1242         VK_BLEND_OP_ADD,                     // VkBlendOp colorBlendOp;
1243         VK_BLEND_FACTOR_ONE,                 // VkBlendFactor srcAlphaBlendFactor;
1244         VK_BLEND_FACTOR_ONE,                 // VkBlendFactor dstAlphaBlendFactor;
1245         VK_BLEND_OP_ADD,                     // VkBlendOp alphaBlendOp;
1246         VK_COLOR_COMPONENT_R_BIT |           // VkColorComponentFlags colorWriteMask;
1247             VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT};
1248 
1249     const VkPipelineColorBlendStateCreateInfo colorBlendStateParams = {
1250         VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
1251         DE_NULL,                                                  // const void* pNext;
1252         0u,                                                       // VkPipelineColorBlendStateCreateFlags flags;
1253         VK_FALSE,                                                 // VkBool32 logicOpEnable;
1254         VK_LOGIC_OP_COPY,                                         // VkLogicOp logicOp;
1255         1u,                                                       // uint32_t attachmentCount;
1256         &colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments;
1257         {0.0f, 0.0f, 0.0f, 0.0f},   // float blendConst[4];
1258     };
1259 
1260     VkPipelineTessellationStateCreateInfo TessellationState = {
1261         VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, // VkStructureType sType;
1262         DE_NULL,                                                   // const void* pNext;
1263         (VkPipelineTessellationStateCreateFlags)0,                 // VkPipelineTessellationStateCreateFlags flags;
1264         4u                                                         // uint32_t patchControlPoints;
1265     };
1266 
1267 #ifndef CTS_USES_VULKANSC
1268     VkPipelineRenderingCreateInfoKHR renderingCreateInfo{VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
1269                                                          DE_NULL,
1270                                                          m_parameters.viewMasks[subpass],
1271                                                          1u,
1272                                                          &m_parameters.colorFormat,
1273                                                          dsFormat,
1274                                                          dsFormat};
1275 #else
1276     DE_UNREF(dsFormat);
1277 #endif // CTS_USES_VULKANSC
1278 
1279     const VkGraphicsPipelineCreateInfo graphicsPipelineParams{
1280         VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
1281 #ifndef CTS_USES_VULKANSC
1282         (renderPass == 0) ? &renderingCreateInfo : DE_NULL, // const void* pNext;
1283 #else
1284         DE_NULL,     // const void* pNext;
1285 #endif                             // CTS_USES_VULKANSC
1286         (VkPipelineCreateFlags)0u, // VkPipelineCreateFlags flags;
1287         pipelineShaderStageCount,  // uint32_t stageCount;
1288         pipelineShaderStageCreate, // const VkPipelineShaderStageCreateInfo* pStages;
1289         &vertexInputStateParams,   // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
1290         &inputAssemblyStateParams, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
1291         (TEST_TYPE_VIEW_INDEX_IN_TESELLATION == m_parameters.viewIndex) ?
1292             &TessellationState :
1293             DE_NULL,              // const VkPipelineTessellationStateCreateInfo* pTessellationState;
1294         &viewportStateParams,     // const VkPipelineViewportStateCreateInfo* pViewportState;
1295         &rasterStateParams,       // const VkPipelineRasterizationStateCreateInfo* pRasterState;
1296         &multisampleStateParams,  // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
1297         &depthStencilStateParams, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
1298         &colorBlendStateParams,   // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
1299         (const VkPipelineDynamicStateCreateInfo *)DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState;
1300         pipelineLayout,                                    // VkPipelineLayout layout;
1301         renderPass,                                        // VkRenderPass renderPass;
1302         subpass,                                           // uint32_t subpass;
1303         0u,                                                // VkPipeline basePipelineHandle;
1304         0,                                                 // int32_t basePipelineIndex;
1305     };
1306 
1307     return createGraphicsPipeline(*m_device, *m_logicalDevice, DE_NULL, &graphicsPipelineParams);
1308 }
1309 
readImage(VkImage image,const tcu::PixelBufferAccess & dst)1310 void MultiViewRenderTestInstance::readImage(VkImage image, const tcu::PixelBufferAccess &dst)
1311 {
1312     Move<VkBuffer> buffer;
1313     MovePtr<Allocation> bufferAlloc;
1314     const VkDeviceSize pixelDataSize =
1315         dst.getWidth() * dst.getHeight() * dst.getDepth() * mapVkFormat(m_parameters.colorFormat).getPixelSize();
1316 
1317     // Create destination buffer
1318     {
1319         const VkBufferCreateInfo bufferParams = {
1320             VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
1321             DE_NULL,                              // const void* pNext;
1322             0u,                                   // VkBufferCreateFlags flags;
1323             pixelDataSize,                        // VkDeviceSize size;
1324             VK_BUFFER_USAGE_TRANSFER_DST_BIT,     // VkBufferUsageFlags usage;
1325             VK_SHARING_MODE_EXCLUSIVE,            // VkSharingMode sharingMode;
1326             1u,                                   // uint32_t queueFamilyIndexCount;
1327             &m_queueFamilyIndex,                  // const uint32_t* pQueueFamilyIndices;
1328         };
1329 
1330         buffer      = createBuffer(*m_device, *m_logicalDevice, &bufferParams);
1331         bufferAlloc = m_allocator->allocate(getBufferMemoryRequirements(*m_device, *m_logicalDevice, *buffer),
1332                                             MemoryRequirement::HostVisible);
1333         VK_CHECK(
1334             m_device->bindBufferMemory(*m_logicalDevice, *buffer, bufferAlloc->getMemory(), bufferAlloc->getOffset()));
1335 
1336         deMemset(bufferAlloc->getHostPtr(), 0, static_cast<size_t>(pixelDataSize));
1337         flushAlloc(*m_device, *m_logicalDevice, *bufferAlloc);
1338     }
1339 
1340     const VkBufferMemoryBarrier bufferBarrier = {
1341         VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
1342         DE_NULL,                                 // const void* pNext;
1343         VK_ACCESS_TRANSFER_WRITE_BIT,            // VkAccessFlags srcAccessMask;
1344         VK_ACCESS_HOST_READ_BIT,                 // VkAccessFlags dstAccessMask;
1345         VK_QUEUE_FAMILY_IGNORED,                 // uint32_t srcQueueFamilyIndex;
1346         VK_QUEUE_FAMILY_IGNORED,                 // uint32_t dstQueueFamilyIndex;
1347         *buffer,                                 // VkBuffer buffer;
1348         0u,                                      // VkDeviceSize offset;
1349         pixelDataSize                            // VkDeviceSize size;
1350     };
1351 
1352     // Copy image to buffer
1353     const VkImageAspectFlags aspect    = getAspectFlags(dst.getFormat());
1354     const VkBufferImageCopy copyRegion = {
1355         0u,                        // VkDeviceSize bufferOffset;
1356         (uint32_t)dst.getWidth(),  // uint32_t bufferRowLength;
1357         (uint32_t)dst.getHeight(), // uint32_t bufferImageHeight;
1358         {
1359             aspect,                                                 // VkImageAspectFlags aspect;
1360             0u,                                                     // uint32_t mipLevel;
1361             0u,                                                     // uint32_t baseArrayLayer;
1362             m_parameters.extent.depth,                              // uint32_t layerCount;
1363         },                                                          // VkImageSubresourceLayers imageSubresource;
1364         {0, 0, 0},                                                  // VkOffset3D imageOffset;
1365         {m_parameters.extent.width, m_parameters.extent.height, 1u} // VkExtent3D imageExtent;
1366     };
1367 
1368     beginCommandBuffer(*m_device, *m_cmdBuffer);
1369     {
1370         VkImageSubresourceRange subresourceRange = {
1371             aspect,                    // VkImageAspectFlags aspectMask;
1372             0u,                        // uint32_t baseMipLevel;
1373             1u,                        // uint32_t mipLevels;
1374             0u,                        // uint32_t baseArraySlice;
1375             m_parameters.extent.depth, // uint32_t arraySize;
1376         };
1377 
1378         imageBarrier(*m_device, *m_cmdBuffer, image, subresourceRange, VK_IMAGE_LAYOUT_GENERAL,
1379                      VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
1380                      VK_ACCESS_TRANSFER_READ_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
1381                      VK_PIPELINE_STAGE_TRANSFER_BIT);
1382 
1383         m_device->cmdCopyImageToBuffer(*m_cmdBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *buffer, 1u,
1384                                        &copyRegion);
1385         m_device->cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
1386                                      (VkDependencyFlags)0, 0, (const VkMemoryBarrier *)DE_NULL, 1, &bufferBarrier, 0u,
1387                                      DE_NULL);
1388     }
1389     VK_CHECK(m_device->endCommandBuffer(*m_cmdBuffer));
1390     submitCommandsAndWait(*m_device, *m_logicalDevice, m_queue, *m_cmdBuffer);
1391 
1392     // Read buffer data
1393     invalidateAlloc(*m_device, *m_logicalDevice, *bufferAlloc);
1394     tcu::copy(dst, tcu::ConstPixelBufferAccess(dst.getFormat(), dst.getSize(), bufferAlloc->getHostPtr()));
1395 }
1396 
checkImage(tcu::ConstPixelBufferAccess & renderedFrame)1397 bool MultiViewRenderTestInstance::checkImage(tcu::ConstPixelBufferAccess &renderedFrame)
1398 {
1399     const MovePtr<tcu::Texture2DArray> referenceFrame = imageData();
1400     const bool result = tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Result",
1401                                                    "Image comparison result", referenceFrame->getLevel(0),
1402                                                    renderedFrame, tcu::Vec4(0.01f), tcu::COMPARE_LOG_EVERYTHING);
1403 
1404     if (!result)
1405         for (uint32_t layerNdx = 0u; layerNdx < m_parameters.extent.depth; layerNdx++)
1406         {
1407             tcu::ConstPixelBufferAccess ref(mapVkFormat(m_parameters.colorFormat), m_parameters.extent.width,
1408                                             m_parameters.extent.height, 1u,
1409                                             referenceFrame->getLevel(0).getPixelPtr(0, 0, layerNdx));
1410             tcu::ConstPixelBufferAccess dst(mapVkFormat(m_parameters.colorFormat), m_parameters.extent.width,
1411                                             m_parameters.extent.height, 1u, renderedFrame.getPixelPtr(0, 0, layerNdx));
1412             tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Result", "Image comparison result", ref,
1413                                        dst, tcu::Vec4(0.01f), tcu::COMPARE_LOG_EVERYTHING);
1414         }
1415 
1416     return result;
1417 }
1418 
getQuarterRefColor(const uint32_t quarterNdx,const int colorNdx,const int layerNdx,const bool background,const uint32_t subpassNdx) const1419 const tcu::Vec4 MultiViewRenderTestInstance::getQuarterRefColor(const uint32_t quarterNdx, const int colorNdx,
1420                                                                 const int layerNdx, const bool background,
1421                                                                 const uint32_t subpassNdx) const
1422 {
1423     // this function is used for genrating same colors while rendering and while creating reference
1424 
1425     switch (m_parameters.viewIndex)
1426     {
1427     case TEST_TYPE_VIEW_MASK:
1428     case TEST_TYPE_VIEW_MASK_ITERATION:
1429         return m_vertexColor[colorNdx];
1430 
1431     case TEST_TYPE_DRAW_INDEXED:
1432         return m_vertexColor[m_vertexIndices[colorNdx]];
1433 
1434     case TEST_TYPE_INSTANCED_RENDERING:
1435         return m_vertexColor[0] +
1436                tcu::Vec4(0.0, static_cast<float>(layerNdx) * 0.10f, static_cast<float>(quarterNdx + 1u) * 0.10f, 0.0);
1437 
1438     case TEST_TYPE_INPUT_RATE_INSTANCE:
1439         return m_vertexColor[colorNdx / 4] +
1440                tcu::Vec4(0.0, static_cast<float>(layerNdx) * 0.10f, static_cast<float>(quarterNdx + 1u) * 0.10f, 0.0);
1441 
1442     case TEST_TYPE_DRAW_INDIRECT_INDEXED:
1443         return m_vertexColor[m_vertexIndices[colorNdx]] +
1444                tcu::Vec4(0.0, static_cast<float>(layerNdx) * 0.10f, 0.0, 0.0);
1445 
1446     case TEST_TYPE_VIEW_INDEX_IN_VERTEX:
1447     case TEST_TYPE_VIEW_INDEX_IN_FRAGMENT:
1448     case TEST_TYPE_VIEW_INDEX_IN_GEOMETRY:
1449     case TEST_TYPE_VIEW_INDEX_IN_TESELLATION:
1450     case TEST_TYPE_INPUT_ATTACHMENTS:
1451     case TEST_TYPE_INPUT_ATTACHMENTS_GEOMETRY:
1452     case TEST_TYPE_DRAW_INDIRECT:
1453     case TEST_TYPE_CLEAR_ATTACHMENTS:
1454     case TEST_TYPE_SECONDARY_CMD_BUFFER:
1455     case TEST_TYPE_SECONDARY_CMD_BUFFER_GEOMETRY:
1456     case TEST_TYPE_NESTED_CMD_BUFFER:
1457         return m_vertexColor[colorNdx] + tcu::Vec4(0.0, static_cast<float>(layerNdx) * 0.10f, 0.0, 0.0);
1458 
1459     case TEST_TYPE_READBACK_WITH_EXPLICIT_CLEAR:
1460         if (background)
1461             return m_colorTable[4 + quarterNdx % 4];
1462         else
1463             return m_colorTable[layerNdx % 4];
1464 
1465     case TEST_TYPE_READBACK_WITH_IMPLICIT_CLEAR:
1466         if (background)
1467             return m_colorTable[4 + quarterNdx % 4];
1468         else
1469             return m_colorTable[0];
1470 
1471     case TEST_TYPE_POINT_SIZE:
1472     case TEST_TYPE_MULTISAMPLE:
1473         if (background)
1474             return tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f);
1475         else
1476             return m_vertexColor[colorNdx];
1477 
1478     case TEST_TYPE_DEPTH:
1479         if (background)
1480             if (subpassNdx < 4)
1481                 return tcu::Vec4(0.66f, 0.0f, 0.0f, 1.0f);
1482             else
1483                 return tcu::Vec4(0.33f, 0.0f, 0.0f, 1.0f);
1484         else
1485             return tcu::Vec4(0.99f, 0.0f, 0.0f, 1.0f);
1486 
1487     case TEST_TYPE_DEPTH_DIFFERENT_RANGES:
1488         // for quads from partA generate  1.20, 0.90, 0.60,  0.30
1489         // for quads from partB generate  0.55, 0.35, 0.15, -0.05
1490         // depth ranges in views are <0;0.5>, <0;1> or <0.5;1> so
1491         // at least one quad from partA/partB will always be drawn
1492         if (subpassNdx < 4)
1493             return tcu::Vec4(1.2f - 0.3f * static_cast<float>(subpassNdx), 0.0f, 0.0f, 1.0f);
1494         return tcu::Vec4(0.55f - 0.2f * static_cast<float>(subpassNdx % 4), 0.0f, 0.0f, 1.0f);
1495 
1496     case TEST_TYPE_STENCIL:
1497         if (background)
1498             return tcu::Vec4(0.33f, 0.0f, 0.0f, 0.0f); // Increment value
1499         else
1500             return tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
1501 
1502     default:
1503         TCU_THROW(InternalError, "Impossible");
1504     }
1505 }
1506 
setPoint(const tcu::PixelBufferAccess & pixelBuffer,const tcu::Vec4 & pointColor,const int pointSize,const int layerNdx,const uint32_t quarter) const1507 void MultiViewRenderTestInstance::setPoint(const tcu::PixelBufferAccess &pixelBuffer, const tcu::Vec4 &pointColor,
1508                                            const int pointSize, const int layerNdx, const uint32_t quarter) const
1509 {
1510     DE_ASSERT(TEST_POINT_SIZE_WIDE > TEST_POINT_SIZE_SMALL);
1511 
1512     const int pointOffset = 1 + TEST_POINT_SIZE_WIDE / 2 - (pointSize + 1) / 2;
1513     const int offsetX =
1514         pointOffset + static_cast<int>((quarter == 0u || quarter == 1u) ? 0 : m_parameters.extent.width / 2u);
1515     const int offsetY =
1516         pointOffset + static_cast<int>((quarter == 0u || quarter == 2u) ? 0 : m_parameters.extent.height / 2u);
1517 
1518     for (int y = 0; y < pointSize; ++y)
1519         for (int x = 0; x < pointSize; ++x)
1520             pixelBuffer.setPixel(pointColor, offsetX + x, offsetY + y, layerNdx);
1521 }
1522 
fillTriangle(const tcu::PixelBufferAccess & pixelBuffer,const tcu::Vec4 & color,const int layerNdx,const uint32_t quarter) const1523 void MultiViewRenderTestInstance::fillTriangle(const tcu::PixelBufferAccess &pixelBuffer, const tcu::Vec4 &color,
1524                                                const int layerNdx, const uint32_t quarter) const
1525 {
1526     const int offsetX = static_cast<int>((quarter == 0u || quarter == 1u) ? 0 : m_parameters.extent.width / 2u);
1527     const int offsetY = static_cast<int>((quarter == 0u || quarter == 2u) ? 0 : m_parameters.extent.height / 2u);
1528     const int maxY    = static_cast<int>(m_parameters.extent.height / 2u);
1529     const tcu::Vec4 multisampledColor = tcu::Vec4(color[0], color[1], color[2], color[3]) * 0.5f;
1530 
1531     for (int y = 0; y < maxY; ++y)
1532     {
1533         for (int x = 0; x < y; ++x)
1534             pixelBuffer.setPixel(color, offsetX + x, offsetY + (maxY - 1) - y, layerNdx);
1535 
1536         // Multisampled pixel is on the triangle margin
1537         pixelBuffer.setPixel(multisampledColor, offsetX + y, offsetY + (maxY - 1) - y, layerNdx);
1538     }
1539 }
1540 
fillLayer(const tcu::PixelBufferAccess & pixelBuffer,const tcu::Vec4 & color,const int layerNdx) const1541 void MultiViewRenderTestInstance::fillLayer(const tcu::PixelBufferAccess &pixelBuffer, const tcu::Vec4 &color,
1542                                             const int layerNdx) const
1543 {
1544     for (uint32_t y = 0u; y < m_parameters.extent.height; ++y)
1545         for (uint32_t x = 0u; x < m_parameters.extent.width; ++x)
1546             pixelBuffer.setPixel(color, x, y, layerNdx);
1547 }
1548 
fillQuarter(const tcu::PixelBufferAccess & pixelBuffer,const tcu::Vec4 & color,const int layerNdx,const uint32_t quarter,const uint32_t subpassNdx) const1549 void MultiViewRenderTestInstance::fillQuarter(const tcu::PixelBufferAccess &pixelBuffer, const tcu::Vec4 &color,
1550                                               const int layerNdx, const uint32_t quarter,
1551                                               const uint32_t subpassNdx) const
1552 {
1553     const int h  = m_parameters.extent.height;
1554     const int h2 = h / 2;
1555     const int w  = m_parameters.extent.width;
1556     const int w2 = w / 2;
1557     int xStart   = 0;
1558     int xEnd     = 0;
1559     int yStart   = 0;
1560     int yEnd     = 0;
1561 
1562     switch (quarter)
1563     {
1564     case 0:
1565         xStart = 0u;
1566         xEnd   = w2;
1567         yStart = 0u;
1568         yEnd   = h2;
1569         break;
1570     case 1:
1571         xStart = 0u;
1572         xEnd   = w2;
1573         yStart = h2;
1574         yEnd   = h;
1575         break;
1576     case 2:
1577         xStart = w2;
1578         xEnd   = w;
1579         yStart = 0u;
1580         yEnd   = h2;
1581         break;
1582     case 3:
1583         xStart = w2;
1584         xEnd   = w;
1585         yStart = h2;
1586         yEnd   = h;
1587         break;
1588     default:
1589         TCU_THROW(InternalError, "Impossible");
1590     }
1591 
1592     if (TEST_TYPE_STENCIL == m_parameters.viewIndex || TEST_TYPE_DEPTH == m_parameters.viewIndex ||
1593         TEST_TYPE_DEPTH_DIFFERENT_RANGES == m_parameters.viewIndex)
1594     {
1595         if (subpassNdx < 4)
1596         { // Part A: Horizontal bars near X axis
1597             yStart = h2 + (yStart - h2) / 2;
1598             yEnd   = h2 + (yEnd - h2) / 2;
1599         }
1600         else
1601         { // Part B: Vertical bars near Y axis (drawn twice)
1602             xStart = w2 + (xStart - w2) / 2;
1603             xEnd   = w2 + (xEnd - w2) / 2;
1604         }
1605 
1606         // Update pixels in area
1607         if (TEST_TYPE_STENCIL == m_parameters.viewIndex)
1608         {
1609             for (int y = yStart; y < yEnd; ++y)
1610                 for (int x = xStart; x < xEnd; ++x)
1611                     pixelBuffer.setPixel(pixelBuffer.getPixel(x, y, layerNdx) + color, x, y, layerNdx);
1612         }
1613 
1614         if (TEST_TYPE_DEPTH == m_parameters.viewIndex || TEST_TYPE_DEPTH_DIFFERENT_RANGES == m_parameters.viewIndex)
1615         {
1616             for (int y = yStart; y < yEnd; ++y)
1617                 for (int x = xStart; x < xEnd; ++x)
1618                 {
1619                     const tcu::Vec4 currentColor = pixelBuffer.getPixel(x, y, layerNdx);
1620                     const tcu::Vec4 &newColor    = (currentColor[0] < color[0]) ? currentColor : color;
1621 
1622                     pixelBuffer.setPixel(newColor, x, y, layerNdx);
1623                 }
1624         }
1625     }
1626     else
1627     {
1628         for (int y = yStart; y < yEnd; ++y)
1629             for (int x = xStart; x < xEnd; ++x)
1630                 pixelBuffer.setPixel(color, x, y, layerNdx);
1631     }
1632 }
1633 
imageData(void) const1634 MovePtr<tcu::Texture2DArray> MultiViewRenderTestInstance::imageData(void) const
1635 {
1636     MovePtr<tcu::Texture2DArray> referenceFrame = MovePtr<tcu::Texture2DArray>(
1637         new tcu::Texture2DArray(mapVkFormat(m_parameters.colorFormat), m_parameters.extent.width,
1638                                 m_parameters.extent.height, m_parameters.extent.depth));
1639     const uint32_t subpassCount = static_cast<uint32_t>(m_parameters.viewMasks.size());
1640     referenceFrame->allocLevel(0);
1641 
1642     deMemset(referenceFrame->getLevel(0).getDataPtr(), 0,
1643              m_parameters.extent.width * m_parameters.extent.height * m_parameters.extent.depth *
1644                  mapVkFormat(m_parameters.colorFormat).getPixelSize());
1645 
1646     if (TEST_TYPE_READBACK_WITH_IMPLICIT_CLEAR == m_parameters.viewIndex ||
1647         TEST_TYPE_READBACK_WITH_EXPLICIT_CLEAR == m_parameters.viewIndex)
1648     {
1649         uint32_t clearedViewMask = 0;
1650 
1651         // Start from last clear command color, which actually takes effect
1652         for (int subpassNdx = static_cast<int>(subpassCount) - 1; subpassNdx >= 0; --subpassNdx)
1653         {
1654             uint32_t subpassToClearViewMask = m_parameters.viewMasks[subpassNdx] & ~clearedViewMask;
1655 
1656             if (subpassToClearViewMask == 0)
1657                 continue;
1658 
1659             for (uint32_t layerNdx = 0; layerNdx < m_parameters.extent.depth; ++layerNdx)
1660                 if ((subpassToClearViewMask & (1 << layerNdx)) != 0 && (clearedViewMask & (1 << layerNdx)) == 0)
1661                     fillLayer(referenceFrame->getLevel(0), getQuarterRefColor(0u, 0u, subpassNdx, false), layerNdx);
1662 
1663             // These has been cleared. Exclude these layers from upcoming attempts to clear
1664             clearedViewMask |= subpassToClearViewMask;
1665         }
1666     }
1667 
1668     for (uint32_t subpassNdx = 0u; subpassNdx < subpassCount; subpassNdx++)
1669     {
1670         int layerNdx  = 0;
1671         uint32_t mask = m_parameters.viewMasks[subpassNdx];
1672 
1673         // iterate over image layers
1674         while (mask > 0u)
1675         {
1676             int colorNdx = 0;
1677 
1678             if (mask & 1u)
1679             {
1680                 if (TEST_TYPE_CLEAR_ATTACHMENTS == m_parameters.viewIndex)
1681                 {
1682                     struct ColorDataRGBA
1683                     {
1684                         uint8_t r;
1685                         uint8_t g;
1686                         uint8_t b;
1687                         uint8_t a;
1688                     };
1689 
1690                     ColorDataRGBA clear = {tcu::floatToU8(1.0f), tcu::floatToU8(0.0f), tcu::floatToU8(0.0f),
1691                                            tcu::floatToU8(1.0f)};
1692 
1693                     ColorDataRGBA *dataSrc = (ColorDataRGBA *)referenceFrame->getLevel(0).getPixelPtr(0, 0, layerNdx);
1694                     ColorDataRGBA *dataDes = dataSrc + 1;
1695                     uint32_t copySize      = 1u;
1696                     uint32_t layerSize     = m_parameters.extent.width * m_parameters.extent.height - copySize;
1697                     deMemcpy(dataSrc, &clear, sizeof(ColorDataRGBA));
1698 
1699                     while (layerSize > 0)
1700                     {
1701                         deMemcpy(dataDes, dataSrc, copySize * sizeof(ColorDataRGBA));
1702                         dataDes   = dataDes + copySize;
1703                         layerSize = layerSize - copySize;
1704                         copySize  = 2u * copySize;
1705                         if (copySize >= layerSize)
1706                             copySize = layerSize;
1707                     }
1708                 }
1709 
1710                 const uint32_t subpassQuarterNdx = subpassNdx % m_squareCount;
1711                 if (subpassQuarterNdx == 0u || TEST_TYPE_INPUT_RATE_INSTANCE == m_parameters.viewIndex)
1712                 {
1713                     const tcu::Vec4 color = getQuarterRefColor(0u, colorNdx, layerNdx, true, subpassNdx);
1714 
1715                     fillQuarter(referenceFrame->getLevel(0), color, layerNdx, 0u, subpassNdx);
1716                 }
1717 
1718                 colorNdx += 4;
1719                 if (subpassQuarterNdx == 1u || subpassCount == 1u ||
1720                     TEST_TYPE_INPUT_RATE_INSTANCE == m_parameters.viewIndex)
1721                 {
1722                     const tcu::Vec4 color = getQuarterRefColor(1u, colorNdx, layerNdx, true, subpassNdx);
1723 
1724                     fillQuarter(referenceFrame->getLevel(0), color, layerNdx, 1u, subpassNdx);
1725                 }
1726 
1727                 colorNdx += 4;
1728                 if (subpassQuarterNdx == 2u || subpassCount == 1u ||
1729                     TEST_TYPE_INPUT_RATE_INSTANCE == m_parameters.viewIndex)
1730                 {
1731                     const tcu::Vec4 color = getQuarterRefColor(2u, colorNdx, layerNdx, true, subpassNdx);
1732 
1733                     fillQuarter(referenceFrame->getLevel(0), color, layerNdx, 2u, subpassNdx);
1734                 }
1735 
1736                 colorNdx += 4;
1737                 if (subpassQuarterNdx == 3u || subpassCount == 1u ||
1738                     TEST_TYPE_INPUT_RATE_INSTANCE == m_parameters.viewIndex)
1739                 {
1740                     const tcu::Vec4 color = getQuarterRefColor(3u, colorNdx, layerNdx, true, subpassNdx);
1741 
1742                     fillQuarter(referenceFrame->getLevel(0), color, layerNdx, 3u, subpassNdx);
1743                 }
1744 
1745                 if (TEST_TYPE_CLEAR_ATTACHMENTS == m_parameters.viewIndex)
1746                 {
1747                     const tcu::Vec4 color(0.0f, 0.0f, 1.0f, 1.0f);
1748                     const int maxY = static_cast<int>(static_cast<float>(m_parameters.extent.height) * 0.75f);
1749                     const int maxX = static_cast<int>(static_cast<float>(m_parameters.extent.width) * 0.75f);
1750                     for (int y = static_cast<int>(m_parameters.extent.height / 4u); y < maxY; ++y)
1751                         for (int x = static_cast<int>(m_parameters.extent.width / 4u); x < maxX; ++x)
1752                             referenceFrame->getLevel(0).setPixel(color, x, y, layerNdx);
1753                 }
1754 
1755                 if (TEST_TYPE_POINT_SIZE == m_parameters.viewIndex)
1756                 {
1757                     const uint32_t vertexPerPrimitive = 1u;
1758                     const uint32_t unusedQuarterNdx   = 0u;
1759                     const int pointSize =
1760                         static_cast<int>(layerNdx == 0u ? TEST_POINT_SIZE_WIDE : TEST_POINT_SIZE_SMALL);
1761 
1762                     if (subpassCount == 1)
1763                         for (uint32_t drawNdx = 0u; drawNdx < m_squareCount; ++drawNdx)
1764                             setPoint(
1765                                 referenceFrame->getLevel(0),
1766                                 getQuarterRefColor(unusedQuarterNdx, vertexPerPrimitive * drawNdx, layerNdx, false),
1767                                 pointSize, layerNdx, drawNdx);
1768                     else
1769                         setPoint(referenceFrame->getLevel(0),
1770                                  getQuarterRefColor(unusedQuarterNdx, vertexPerPrimitive * subpassQuarterNdx, layerNdx,
1771                                                     false),
1772                                  pointSize, layerNdx, subpassQuarterNdx);
1773                 }
1774 
1775                 if (TEST_TYPE_MULTISAMPLE == m_parameters.viewIndex)
1776                 {
1777                     const uint32_t vertexPerPrimitive = 3u;
1778                     const uint32_t unusedQuarterNdx   = 0u;
1779 
1780                     if (subpassCount == 1)
1781                         for (uint32_t drawNdx = 0u; drawNdx < m_squareCount; ++drawNdx)
1782                             fillTriangle(
1783                                 referenceFrame->getLevel(0),
1784                                 getQuarterRefColor(unusedQuarterNdx, vertexPerPrimitive * drawNdx, layerNdx, false),
1785                                 layerNdx, drawNdx);
1786                     else
1787                         fillTriangle(referenceFrame->getLevel(0),
1788                                      getQuarterRefColor(unusedQuarterNdx, vertexPerPrimitive * subpassQuarterNdx,
1789                                                         layerNdx, false),
1790                                      layerNdx, subpassQuarterNdx);
1791                 }
1792             }
1793 
1794             mask = mask >> 1;
1795             ++layerNdx;
1796         }
1797     }
1798     return referenceFrame;
1799 }
1800 
appendVertex(const tcu::Vec4 & coord,const tcu::Vec4 & color)1801 void MultiViewRenderTestInstance::appendVertex(const tcu::Vec4 &coord, const tcu::Vec4 &color)
1802 {
1803     m_vertexCoord.push_back(coord);
1804     m_vertexColor.push_back(color);
1805 }
1806 
1807 class MultiViewAttachmentsTestInstance : public MultiViewRenderTestInstance
1808 {
1809 public:
1810     MultiViewAttachmentsTestInstance(Context &context, const TestParameters &parameters);
1811 
1812 protected:
1813     tcu::TestStatus iterate(void) override;
1814     void beforeRenderPass(void) override;
1815     void bindResources(void) override;
1816     void setImageData(VkImage image);
1817     de::SharedPtr<ImageAttachment> m_inputAttachment;
1818     Move<VkDescriptorPool> m_descriptorPool;
1819     Move<VkDescriptorSet> m_descriptorSet;
1820     Move<VkDescriptorSetLayout> m_descriptorSetLayout;
1821     Move<VkPipelineLayout> m_pipelineLayout;
1822 };
1823 
MultiViewAttachmentsTestInstance(Context & context,const TestParameters & parameters)1824 MultiViewAttachmentsTestInstance::MultiViewAttachmentsTestInstance(Context &context, const TestParameters &parameters)
1825     : MultiViewRenderTestInstance(context, parameters)
1826 {
1827 }
1828 
iterate(void)1829 tcu::TestStatus MultiViewAttachmentsTestInstance::iterate(void)
1830 {
1831     const uint32_t subpassCount = static_cast<uint32_t>(m_parameters.viewMasks.size());
1832     Move<VkRenderPass> renderPass;
1833     Move<VkFramebuffer> frameBuffer;
1834 
1835     // All color attachment
1836     m_colorAttachment = de::SharedPtr<ImageAttachment>(
1837         new ImageAttachment(*m_logicalDevice, *m_device, *m_allocator, m_parameters.extent, m_parameters.colorFormat));
1838     m_inputAttachment = de::SharedPtr<ImageAttachment>(
1839         new ImageAttachment(*m_logicalDevice, *m_device, *m_allocator, m_parameters.extent, m_parameters.colorFormat));
1840 
1841     // FrameBuffer & renderPass
1842     if (m_parameters.renderingType != RENDERING_TYPE_DYNAMIC_RENDERING)
1843     {
1844         vector<VkImageView> attachments{m_colorAttachment->getImageView(), m_inputAttachment->getImageView()};
1845         renderPass = makeRenderPassWithAttachments(*m_device, *m_logicalDevice, m_parameters.colorFormat,
1846                                                    m_parameters.viewMasks, m_parameters.renderingType);
1847         frameBuffer =
1848             makeFramebuffer(*m_device, *m_logicalDevice, *renderPass, static_cast<uint32_t>(attachments.size()),
1849                             attachments.data(), m_parameters.extent.width, m_parameters.extent.height);
1850     }
1851 
1852     // pipelineLayout
1853     m_descriptorSetLayout = makeDescriptorSetLayout(*m_device, *m_logicalDevice);
1854     m_pipelineLayout      = makePipelineLayout(*m_device, *m_logicalDevice, m_descriptorSetLayout.get());
1855 
1856     // pipelines
1857     map<VkShaderStageFlagBits, ShaderModuleSP> shaderModule;
1858     vector<PipelineSp> pipelines(subpassCount);
1859 
1860     {
1861         vector<VkPipelineShaderStageCreateInfo> shaderStageParams;
1862         madeShaderModule(shaderModule, shaderStageParams);
1863         for (uint32_t subpassNdx = 0u; subpassNdx < subpassCount; ++subpassNdx)
1864             pipelines[subpassNdx] = (PipelineSp(new Unique<VkPipeline>(
1865                 makeGraphicsPipeline(*renderPass, *m_pipelineLayout, static_cast<uint32_t>(shaderStageParams.size()),
1866                                      shaderStageParams.data(), subpassNdx))));
1867     }
1868 
1869     createVertexData();
1870     createVertexBuffer();
1871 
1872     createCommandBuffer();
1873     setImageData(m_inputAttachment->getImage());
1874     draw(subpassCount, *renderPass, *frameBuffer, pipelines);
1875 
1876     {
1877         vector<uint8_t> pixelAccessData(m_parameters.extent.width * m_parameters.extent.height *
1878                                         m_parameters.extent.depth *
1879                                         mapVkFormat(m_parameters.colorFormat).getPixelSize());
1880         tcu::PixelBufferAccess dst(mapVkFormat(m_parameters.colorFormat), m_parameters.extent.width,
1881                                    m_parameters.extent.height, m_parameters.extent.depth, pixelAccessData.data());
1882 
1883         readImage(m_colorAttachment->getImage(), dst);
1884         if (!checkImage(dst))
1885             return tcu::TestStatus::fail("Fail");
1886     }
1887 
1888     return tcu::TestStatus::pass("Pass");
1889 }
1890 
beforeRenderPass(void)1891 void MultiViewAttachmentsTestInstance::beforeRenderPass(void)
1892 {
1893     const VkDescriptorPoolSize poolSize = {vk::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1u};
1894 
1895     const VkDescriptorPoolCreateInfo createInfo = {vk::VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
1896                                                    DE_NULL,
1897                                                    VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
1898                                                    1u,
1899                                                    1u,
1900                                                    &poolSize};
1901 
1902     m_descriptorPool = createDescriptorPool(*m_device, *m_logicalDevice, &createInfo);
1903 
1904     const VkDescriptorSetAllocateInfo allocateInfo = {vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, DE_NULL,
1905                                                       *m_descriptorPool, 1u, &m_descriptorSetLayout.get()};
1906 
1907     m_descriptorSet = vk::allocateDescriptorSet(*m_device, *m_logicalDevice, &allocateInfo);
1908 
1909     const VkDescriptorImageInfo imageInfo = {(VkSampler)0, m_inputAttachment->getImageView(), VK_IMAGE_LAYOUT_GENERAL};
1910 
1911     const VkWriteDescriptorSet write = {
1912         VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, //VkStructureType sType;
1913         DE_NULL,                                //const void* pNext;
1914         *m_descriptorSet,                       //VkDescriptorSet dstSet;
1915         0u,                                     //uint32_t dstBinding;
1916         0u,                                     //uint32_t dstArrayElement;
1917         1u,                                     //uint32_t descriptorCount;
1918         VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,    //VkDescriptorType descriptorType;
1919         &imageInfo,                             //const VkDescriptorImageInfo* pImageInfo;
1920         DE_NULL,                                //const VkDescriptorBufferInfo* pBufferInfo;
1921         DE_NULL,                                //const VkBufferView* pTexelBufferView;
1922     };
1923 
1924     m_device->updateDescriptorSets(*m_logicalDevice, (uint32_t)1u, &write, 0u, DE_NULL);
1925 
1926     const VkImageSubresourceRange subresourceRange = {
1927         VK_IMAGE_ASPECT_COLOR_BIT, //VkImageAspectFlags aspectMask;
1928         0u,                        //uint32_t baseMipLevel;
1929         1u,                        //uint32_t levelCount;
1930         0u,                        //uint32_t baseArrayLayer;
1931         m_parameters.extent.depth, //uint32_t layerCount;
1932     };
1933 
1934     imageBarrier(*m_device, *m_cmdBuffer, m_colorAttachment->getImage(), subresourceRange, VK_IMAGE_LAYOUT_UNDEFINED,
1935                  VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0, VK_ACCESS_TRANSFER_WRITE_BIT,
1936                  VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
1937 
1938     const VkClearValue renderPassClearValue = makeClearValueColor(tcu::Vec4(0.0f));
1939     m_device->cmdClearColorImage(*m_cmdBuffer, m_colorAttachment->getImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1940                                  &renderPassClearValue.color, 1, &subresourceRange);
1941 
1942     imageBarrier(*m_device, *m_cmdBuffer, m_colorAttachment->getImage(), subresourceRange,
1943                  VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
1944                  VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
1945                  VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
1946 }
1947 
bindResources(void)1948 void MultiViewAttachmentsTestInstance::bindResources(void)
1949 {
1950     m_device->cmdBindDescriptorSets(*m_cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0u, 1u,
1951                                     &(*m_descriptorSet), 0u, NULL);
1952 }
1953 
setImageData(VkImage image)1954 void MultiViewAttachmentsTestInstance::setImageData(VkImage image)
1955 {
1956     const MovePtr<tcu::Texture2DArray> data = imageData();
1957     Move<VkBuffer> buffer;
1958     const uint32_t bufferSize = m_parameters.extent.width * m_parameters.extent.height * m_parameters.extent.depth *
1959                                 tcu::getPixelSize(mapVkFormat(m_parameters.colorFormat));
1960     MovePtr<Allocation> bufferAlloc;
1961 
1962     // Create source buffer
1963     {
1964         const VkBufferCreateInfo bufferParams = {
1965             VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
1966             DE_NULL,                              // const void* pNext;
1967             0u,                                   // VkBufferCreateFlags flags;
1968             bufferSize,                           // VkDeviceSize size;
1969             VK_BUFFER_USAGE_TRANSFER_SRC_BIT,     // VkBufferUsageFlags usage;
1970             VK_SHARING_MODE_EXCLUSIVE,            // VkSharingMode sharingMode;
1971             1u,                                   // uint32_t queueFamilyIndexCount;
1972             &m_queueFamilyIndex,                  // const uint32_t* pQueueFamilyIndices;
1973         };
1974 
1975         buffer      = createBuffer(*m_device, *m_logicalDevice, &bufferParams);
1976         bufferAlloc = m_allocator->allocate(getBufferMemoryRequirements(*m_device, *m_logicalDevice, *buffer),
1977                                             MemoryRequirement::HostVisible);
1978         VK_CHECK(
1979             m_device->bindBufferMemory(*m_logicalDevice, *buffer, bufferAlloc->getMemory(), bufferAlloc->getOffset()));
1980     }
1981 
1982     // Barriers for copying buffer to image
1983     const VkBufferMemoryBarrier preBufferBarrier = {
1984         VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
1985         DE_NULL,                                 // const void* pNext;
1986         VK_ACCESS_HOST_WRITE_BIT,                // VkAccessFlags srcAccessMask;
1987         VK_ACCESS_TRANSFER_READ_BIT,             // VkAccessFlags dstAccessMask;
1988         VK_QUEUE_FAMILY_IGNORED,                 // uint32_t srcQueueFamilyIndex;
1989         VK_QUEUE_FAMILY_IGNORED,                 // uint32_t dstQueueFamilyIndex;
1990         *buffer,                                 // VkBuffer buffer;
1991         0u,                                      // VkDeviceSize offset;
1992         bufferSize                               // VkDeviceSize size;
1993     };
1994 
1995     const VkImageAspectFlags formatAspect    = getAspectFlags(mapVkFormat(m_parameters.colorFormat));
1996     VkImageSubresourceRange subresourceRange = {
1997         // VkImageSubresourceRange subresourceRange;
1998         formatAspect,              // VkImageAspectFlags aspect;
1999         0u,                        // uint32_t baseMipLevel;
2000         1u,                        // uint32_t mipLevels;
2001         0u,                        // uint32_t baseArraySlice;
2002         m_parameters.extent.depth, // uint32_t arraySize;
2003     };
2004 
2005     const VkBufferImageCopy copyRegion = {
2006         0u,                                      // VkDeviceSize bufferOffset;
2007         (uint32_t)data->getLevel(0).getWidth(),  // uint32_t bufferRowLength;
2008         (uint32_t)data->getLevel(0).getHeight(), // uint32_t bufferImageHeight;
2009         {
2010             VK_IMAGE_ASPECT_COLOR_BIT,                              // VkImageAspectFlags aspect;
2011             0u,                                                     // uint32_t mipLevel;
2012             0u,                                                     // uint32_t baseArrayLayer;
2013             m_parameters.extent.depth,                              // uint32_t layerCount;
2014         },                                                          // VkImageSubresourceLayers imageSubresource;
2015         {0, 0, 0},                                                  // VkOffset3D imageOffset;
2016         {m_parameters.extent.width, m_parameters.extent.height, 1u} // VkExtent3D imageExtent;
2017     };
2018 
2019     // Write buffer data
2020     deMemcpy(bufferAlloc->getHostPtr(), data->getLevel(0).getDataPtr(), bufferSize);
2021     flushAlloc(*m_device, *m_logicalDevice, *bufferAlloc);
2022 
2023     beginCommandBuffer(*m_device, *m_cmdBuffer);
2024 
2025     m_device->cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
2026                                  (VkDependencyFlags)0, 0, (const VkMemoryBarrier *)DE_NULL, 1, &preBufferBarrier, 0,
2027                                  (const VkImageMemoryBarrier *)DE_NULL);
2028     imageBarrier(*m_device, *m_cmdBuffer, image, subresourceRange, VK_IMAGE_LAYOUT_UNDEFINED,
2029                  VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0u, VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_HOST_BIT,
2030                  VK_PIPELINE_STAGE_TRANSFER_BIT);
2031     m_device->cmdCopyBufferToImage(*m_cmdBuffer, *buffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &copyRegion);
2032     imageBarrier(*m_device, *m_cmdBuffer, image, subresourceRange, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
2033                  VK_IMAGE_LAYOUT_GENERAL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_WRITE_BIT,
2034                  VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
2035     VK_CHECK(m_device->endCommandBuffer(*m_cmdBuffer));
2036 
2037     submitCommandsAndWait(*m_device, *m_logicalDevice, m_queue, *m_cmdBuffer);
2038 }
2039 
2040 class MultiViewInstancedTestInstance : public MultiViewRenderTestInstance
2041 {
2042 public:
2043     MultiViewInstancedTestInstance(Context &context, const TestParameters &parameters);
2044 
2045 protected:
2046     void createVertexData(void);
2047     void draw(const uint32_t subpassCount, VkRenderPass renderPass, VkFramebuffer frameBuffer,
2048               vector<PipelineSp> &pipelines);
2049 };
2050 
MultiViewInstancedTestInstance(Context & context,const TestParameters & parameters)2051 MultiViewInstancedTestInstance::MultiViewInstancedTestInstance(Context &context, const TestParameters &parameters)
2052     : MultiViewRenderTestInstance(context, parameters)
2053 {
2054 }
2055 
createVertexData(void)2056 void MultiViewInstancedTestInstance::createVertexData(void)
2057 {
2058     const tcu::Vec4 color = tcu::Vec4(0.2f, 0.0f, 0.1f, 1.0f);
2059 
2060     appendVertex(tcu::Vec4(-1.0f, -1.0f, 1.0f, 1.0f), color);
2061     appendVertex(tcu::Vec4(-1.0f, 0.0f, 1.0f, 1.0f), color);
2062     appendVertex(tcu::Vec4(0.0f, -1.0f, 1.0f, 1.0f), color);
2063     appendVertex(tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), color);
2064 }
2065 
draw(const uint32_t subpassCount,VkRenderPass renderPass,VkFramebuffer frameBuffer,vector<PipelineSp> & pipelines)2066 void MultiViewInstancedTestInstance::draw(const uint32_t subpassCount, VkRenderPass renderPass,
2067                                           VkFramebuffer frameBuffer, vector<PipelineSp> &pipelines)
2068 {
2069     const VkRect2D renderArea                = {{0, 0}, {m_parameters.extent.width, m_parameters.extent.height}};
2070     const VkClearValue renderPassClearValue  = makeClearValueColor(tcu::Vec4(0.0f));
2071     const VkBuffer vertexBuffers[]           = {*m_vertexCoordBuffer, *m_vertexColorBuffer};
2072     const VkDeviceSize vertexBufferOffsets[] = {0u, 0u};
2073     const uint32_t drawCountPerSubpass       = (subpassCount == 1) ? m_squareCount : 1u;
2074 
2075     beginCommandBuffer(*m_device, *m_cmdBuffer);
2076 
2077     beforeRenderPass();
2078 
2079     if (!m_useDynamicRendering)
2080     {
2081         const VkRenderPassBeginInfo renderPassBeginInfo = {
2082             VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
2083             DE_NULL,                                  // const void* pNext;
2084             renderPass,                               // VkRenderPass renderPass;
2085             frameBuffer,                              // VkFramebuffer framebuffer;
2086             renderArea,                               // VkRect2D renderArea;
2087             1u,                                       // uint32_t clearValueCount;
2088             &renderPassClearValue,                    // const VkClearValue* pClearValues;
2089         };
2090         cmdBeginRenderPass(*m_device, *m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE,
2091                            m_parameters.renderingType);
2092     }
2093 
2094     for (uint32_t subpassNdx = 0u; subpassNdx < subpassCount; subpassNdx++)
2095     {
2096         m_device->cmdBindVertexBuffers(*m_cmdBuffer, 0u, DE_LENGTH_OF_ARRAY(vertexBuffers), vertexBuffers,
2097                                        vertexBufferOffsets);
2098 
2099 #ifndef CTS_USES_VULKANSC
2100         if (m_useDynamicRendering)
2101         {
2102             addRenderingSubpassDependencyIfRequired(subpassNdx);
2103 
2104             beginRendering(*m_device, *m_cmdBuffer, m_colorAttachment->getImageView(), renderArea, renderPassClearValue,
2105                            VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
2106                            (subpassNdx ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_CLEAR), 0u,
2107                            m_parameters.extent.depth, m_parameters.viewMasks[subpassNdx]);
2108         }
2109 #endif // CTS_USES_VULKANSC
2110 
2111         m_device->cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipelines[subpassNdx]);
2112 
2113         m_device->cmdDraw(*m_cmdBuffer, 4u, drawCountPerSubpass, 0u, subpassNdx % m_squareCount);
2114 
2115 #ifndef CTS_USES_VULKANSC
2116         if (m_useDynamicRendering)
2117             endRendering(*m_device, *m_cmdBuffer);
2118         else
2119 #endif // CTS_USES_VULKANSC
2120             if (subpassNdx < subpassCount - 1u)
2121                 cmdNextSubpass(*m_device, *m_cmdBuffer, VK_SUBPASS_CONTENTS_INLINE, m_parameters.renderingType);
2122     }
2123 
2124     if (!m_useDynamicRendering)
2125         cmdEndRenderPass(*m_device, *m_cmdBuffer, m_parameters.renderingType);
2126 
2127     afterRenderPass();
2128 
2129     VK_CHECK(m_device->endCommandBuffer(*m_cmdBuffer));
2130     submitCommandsAndWait(*m_device, *m_logicalDevice, m_queue, *m_cmdBuffer);
2131 }
2132 
2133 class MultiViewInputRateInstanceTestInstance : public MultiViewRenderTestInstance
2134 {
2135 public:
2136     MultiViewInputRateInstanceTestInstance(Context &context, const TestParameters &parameters);
2137 
2138 protected:
2139     void createVertexData(void);
2140 
2141     void draw(const uint32_t subpassCount, VkRenderPass renderPass, VkFramebuffer frameBuffer,
2142               vector<PipelineSp> &pipelines);
2143 };
2144 
MultiViewInputRateInstanceTestInstance(Context & context,const TestParameters & parameters)2145 MultiViewInputRateInstanceTestInstance::MultiViewInputRateInstanceTestInstance(Context &context,
2146                                                                                const TestParameters &parameters)
2147     : MultiViewRenderTestInstance(context, parameters)
2148 {
2149 }
2150 
createVertexData(void)2151 void MultiViewInputRateInstanceTestInstance::createVertexData(void)
2152 {
2153     appendVertex(tcu::Vec4(-1.0f, -1.0f, 1.0f, 1.0f), tcu::Vec4(0.2f, 0.0f, 0.1f, 1.0f));
2154     appendVertex(tcu::Vec4(-1.0f, 0.0f, 1.0f, 1.0f), tcu::Vec4(0.3f, 0.0f, 0.2f, 1.0f));
2155     appendVertex(tcu::Vec4(0.0f, -1.0f, 1.0f, 1.0f), tcu::Vec4(0.4f, 0.2f, 0.3f, 1.0f));
2156     appendVertex(tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), tcu::Vec4(0.5f, 0.0f, 0.4f, 1.0f));
2157 }
2158 
draw(const uint32_t subpassCount,VkRenderPass renderPass,VkFramebuffer frameBuffer,vector<PipelineSp> & pipelines)2159 void MultiViewInputRateInstanceTestInstance::draw(const uint32_t subpassCount, VkRenderPass renderPass,
2160                                                   VkFramebuffer frameBuffer, vector<PipelineSp> &pipelines)
2161 {
2162     const VkRect2D renderArea                = {{0, 0}, {m_parameters.extent.width, m_parameters.extent.height}};
2163     const VkClearValue renderPassClearValue  = makeClearValueColor(tcu::Vec4(0.0f));
2164     const VkBuffer vertexBuffers[]           = {*m_vertexCoordBuffer, *m_vertexColorBuffer};
2165     const VkDeviceSize vertexBufferOffsets[] = {0u, 0u};
2166     const uint32_t drawCountPerSubpass       = (subpassCount == 1) ? m_squareCount : 1u;
2167 
2168     beginCommandBuffer(*m_device, *m_cmdBuffer);
2169 
2170     beforeRenderPass();
2171 
2172     if (!m_useDynamicRendering)
2173     {
2174         const VkRenderPassBeginInfo renderPassBeginInfo = {
2175             VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
2176             DE_NULL,                                  // const void* pNext;
2177             renderPass,                               // VkRenderPass renderPass;
2178             frameBuffer,                              // VkFramebuffer framebuffer;
2179             renderArea,                               // VkRect2D renderArea;
2180             1u,                                       // uint32_t clearValueCount;
2181             &renderPassClearValue,                    // const VkClearValue* pClearValues;
2182         };
2183         cmdBeginRenderPass(*m_device, *m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE,
2184                            m_parameters.renderingType);
2185     }
2186 
2187     for (uint32_t subpassNdx = 0u; subpassNdx < subpassCount; subpassNdx++)
2188     {
2189         m_device->cmdBindVertexBuffers(*m_cmdBuffer, 0u, DE_LENGTH_OF_ARRAY(vertexBuffers), vertexBuffers,
2190                                        vertexBufferOffsets);
2191 
2192 #ifndef CTS_USES_VULKANSC
2193         if (m_useDynamicRendering)
2194         {
2195             addRenderingSubpassDependencyIfRequired(subpassNdx);
2196 
2197             beginRendering(*m_device, *m_cmdBuffer, m_colorAttachment->getImageView(), renderArea, renderPassClearValue,
2198                            VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
2199                            (subpassNdx ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_CLEAR), 0u,
2200                            m_parameters.extent.depth, m_parameters.viewMasks[subpassNdx]);
2201         }
2202 #endif // CTS_USES_VULKANSC
2203 
2204         m_device->cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipelines[subpassNdx]);
2205 
2206         for (uint32_t drawNdx = 0u; drawNdx < drawCountPerSubpass; ++drawNdx)
2207             m_device->cmdDraw(*m_cmdBuffer, 4u, 4u, 0u, 0u);
2208 
2209 #ifndef CTS_USES_VULKANSC
2210         if (m_useDynamicRendering)
2211             endRendering(*m_device, *m_cmdBuffer);
2212         else
2213 #endif // CTS_USES_VULKANSC
2214             if (subpassNdx < subpassCount - 1u)
2215                 cmdNextSubpass(*m_device, *m_cmdBuffer, VK_SUBPASS_CONTENTS_INLINE, m_parameters.renderingType);
2216     }
2217 
2218     if (!m_useDynamicRendering)
2219         cmdEndRenderPass(*m_device, *m_cmdBuffer, m_parameters.renderingType);
2220 
2221     afterRenderPass();
2222 
2223     VK_CHECK(m_device->endCommandBuffer(*m_cmdBuffer));
2224     submitCommandsAndWait(*m_device, *m_logicalDevice, m_queue, *m_cmdBuffer);
2225 }
2226 
2227 class MultiViewDrawIndirectTestInstance : public MultiViewRenderTestInstance
2228 {
2229 public:
2230     MultiViewDrawIndirectTestInstance(Context &context, const TestParameters &parameters);
2231 
2232 protected:
2233     void draw(const uint32_t subpassCount, VkRenderPass renderPass, VkFramebuffer frameBuffer,
2234               vector<PipelineSp> &pipelines);
2235 };
2236 
MultiViewDrawIndirectTestInstance(Context & context,const TestParameters & parameters)2237 MultiViewDrawIndirectTestInstance::MultiViewDrawIndirectTestInstance(Context &context, const TestParameters &parameters)
2238     : MultiViewRenderTestInstance(context, parameters)
2239 {
2240 }
2241 
draw(const uint32_t subpassCount,VkRenderPass renderPass,VkFramebuffer frameBuffer,vector<PipelineSp> & pipelines)2242 void MultiViewDrawIndirectTestInstance::draw(const uint32_t subpassCount, VkRenderPass renderPass,
2243                                              VkFramebuffer frameBuffer, vector<PipelineSp> &pipelines)
2244 {
2245     typedef de::SharedPtr<Unique<VkBuffer>> BufferSP;
2246     typedef de::SharedPtr<UniquePtr<Allocation>> AllocationSP;
2247 
2248     const size_t nonCoherentAtomSize = static_cast<size_t>(m_context.getDeviceProperties().limits.nonCoherentAtomSize);
2249     const VkRect2D renderArea        = {{0, 0}, {m_parameters.extent.width, m_parameters.extent.height}};
2250     const VkClearValue renderPassClearValue  = makeClearValueColor(tcu::Vec4(0.0f));
2251     const VkBuffer vertexBuffers[]           = {*m_vertexCoordBuffer, *m_vertexColorBuffer};
2252     const VkDeviceSize vertexBufferOffsets[] = {0u, 0u};
2253     const uint32_t drawCountPerSubpass       = (subpassCount == 1) ? m_squareCount : 1u;
2254     const uint32_t strideInBuffer            = (m_parameters.viewIndex == TEST_TYPE_DRAW_INDIRECT_INDEXED) ?
2255                                                    static_cast<uint32_t>(sizeof(vk::VkDrawIndexedIndirectCommand)) :
2256                                                    static_cast<uint32_t>(sizeof(vk::VkDrawIndirectCommand));
2257     vector<BufferSP> indirectBuffers(subpassCount);
2258     vector<AllocationSP> indirectAllocations(subpassCount);
2259 
2260     for (uint32_t subpassNdx = 0u; subpassNdx < subpassCount; subpassNdx++)
2261     {
2262         vector<VkDrawIndirectCommand> drawCommands;
2263         vector<VkDrawIndexedIndirectCommand> drawCommandsIndexed;
2264 
2265         for (uint32_t drawNdx = 0u; drawNdx < drawCountPerSubpass; ++drawNdx)
2266         {
2267             if (m_parameters.viewIndex == TEST_TYPE_DRAW_INDIRECT_INDEXED)
2268             {
2269                 const VkDrawIndexedIndirectCommand drawCommandIndexed = {
2270                     4u,                                          //  uint32_t indexCount;
2271                     1u,                                          //  uint32_t instanceCount;
2272                     (drawNdx + subpassNdx % m_squareCount) * 4u, //  uint32_t firstIndex;
2273                     0u,                                          //  int32_t vertexOffset;
2274                     0u,                                          //  uint32_t firstInstance;
2275                 };
2276 
2277                 drawCommandsIndexed.push_back(drawCommandIndexed);
2278             }
2279             else
2280             {
2281                 const VkDrawIndirectCommand drawCommand = {
2282                     4u,                                          //  uint32_t vertexCount;
2283                     1u,                                          //  uint32_t instanceCount;
2284                     (drawNdx + subpassNdx % m_squareCount) * 4u, //  uint32_t firstVertex;
2285                     0u                                           //  uint32_t firstInstance;
2286                 };
2287 
2288                 drawCommands.push_back(drawCommand);
2289             }
2290         }
2291 
2292         const size_t drawCommandsLength     = (m_parameters.viewIndex == TEST_TYPE_DRAW_INDIRECT_INDEXED) ?
2293                                                   drawCommandsIndexed.size() :
2294                                                   drawCommands.size();
2295         const void *drawCommandsDataPtr     = (m_parameters.viewIndex == TEST_TYPE_DRAW_INDIRECT_INDEXED) ?
2296                                                   (void *)&drawCommandsIndexed[0] :
2297                                                   (void *)&drawCommands[0];
2298         const size_t dataSize               = static_cast<size_t>(drawCommandsLength * strideInBuffer);
2299         const VkDeviceSize bufferDataSize   = static_cast<VkDeviceSize>(deAlignSize(dataSize, nonCoherentAtomSize));
2300         const VkBufferCreateInfo bufferInfo = makeBufferCreateInfo(bufferDataSize, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT);
2301         Move<VkBuffer> indirectBuffer       = createBuffer(*m_device, *m_logicalDevice, &bufferInfo);
2302         MovePtr<Allocation> allocationBuffer = m_allocator->allocate(
2303             getBufferMemoryRequirements(*m_device, *m_logicalDevice, *indirectBuffer), MemoryRequirement::HostVisible);
2304 
2305         DE_ASSERT(drawCommandsLength != 0);
2306 
2307         VK_CHECK(m_device->bindBufferMemory(*m_logicalDevice, *indirectBuffer, allocationBuffer->getMemory(),
2308                                             allocationBuffer->getOffset()));
2309 
2310         deMemcpy(allocationBuffer->getHostPtr(), drawCommandsDataPtr, static_cast<size_t>(dataSize));
2311 
2312         flushAlloc(*m_device, *m_logicalDevice, *allocationBuffer);
2313         indirectBuffers[subpassNdx]     = (BufferSP(new Unique<VkBuffer>(indirectBuffer)));
2314         indirectAllocations[subpassNdx] = (AllocationSP(new UniquePtr<Allocation>(allocationBuffer)));
2315     }
2316 
2317     beginCommandBuffer(*m_device, *m_cmdBuffer);
2318 
2319     beforeRenderPass();
2320 
2321     if (!m_useDynamicRendering)
2322     {
2323         const VkRenderPassBeginInfo renderPassBeginInfo{
2324             VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
2325             DE_NULL,                                  // const void* pNext;
2326             renderPass,                               // VkRenderPass renderPass;
2327             frameBuffer,                              // VkFramebuffer framebuffer;
2328             renderArea,                               // VkRect2D renderArea;
2329             1u,                                       // uint32_t clearValueCount;
2330             &renderPassClearValue,                    // const VkClearValue* pClearValues;
2331         };
2332         cmdBeginRenderPass(*m_device, *m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE,
2333                            m_parameters.renderingType);
2334     }
2335 
2336     for (uint32_t subpassNdx = 0u; subpassNdx < subpassCount; subpassNdx++)
2337     {
2338         m_device->cmdBindVertexBuffers(*m_cmdBuffer, 0u, DE_LENGTH_OF_ARRAY(vertexBuffers), vertexBuffers,
2339                                        vertexBufferOffsets);
2340 
2341         if (m_parameters.viewIndex == TEST_TYPE_DRAW_INDIRECT_INDEXED)
2342             m_device->cmdBindIndexBuffer(*m_cmdBuffer, *m_vertexIndicesBuffer, 0u, VK_INDEX_TYPE_UINT32);
2343 
2344 #ifndef CTS_USES_VULKANSC
2345         if (m_useDynamicRendering)
2346         {
2347             addRenderingSubpassDependencyIfRequired(subpassNdx);
2348 
2349             beginRendering(*m_device, *m_cmdBuffer, m_colorAttachment->getImageView(), renderArea, renderPassClearValue,
2350                            VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
2351                            (subpassNdx ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_CLEAR), 0u,
2352                            m_parameters.extent.depth, m_parameters.viewMasks[subpassNdx]);
2353         }
2354 #endif // CTS_USES_VULKANSC
2355 
2356         m_device->cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipelines[subpassNdx]);
2357 
2358         if (m_hasMultiDrawIndirect)
2359         {
2360             if (m_parameters.viewIndex == TEST_TYPE_DRAW_INDIRECT_INDEXED)
2361                 m_device->cmdDrawIndexedIndirect(*m_cmdBuffer, **indirectBuffers[subpassNdx], 0u, drawCountPerSubpass,
2362                                                  strideInBuffer);
2363             else
2364                 m_device->cmdDrawIndirect(*m_cmdBuffer, **indirectBuffers[subpassNdx], 0u, drawCountPerSubpass,
2365                                           strideInBuffer);
2366         }
2367         else
2368         {
2369             for (uint32_t drawNdx = 0; drawNdx < drawCountPerSubpass; drawNdx++)
2370             {
2371                 if (m_parameters.viewIndex == TEST_TYPE_DRAW_INDIRECT_INDEXED)
2372                     m_device->cmdDrawIndexedIndirect(*m_cmdBuffer, **indirectBuffers[subpassNdx],
2373                                                      drawNdx * strideInBuffer, 1, strideInBuffer);
2374                 else
2375                     m_device->cmdDrawIndirect(*m_cmdBuffer, **indirectBuffers[subpassNdx], drawNdx * strideInBuffer, 1,
2376                                               strideInBuffer);
2377             }
2378         }
2379 
2380 #ifndef CTS_USES_VULKANSC
2381         if (m_useDynamicRendering)
2382             endRendering(*m_device, *m_cmdBuffer);
2383         else
2384 #endif // CTS_USES_VULKANSC
2385             if (subpassNdx < subpassCount - 1u)
2386                 cmdNextSubpass(*m_device, *m_cmdBuffer, VK_SUBPASS_CONTENTS_INLINE, m_parameters.renderingType);
2387     }
2388 
2389     if (!m_useDynamicRendering)
2390         cmdEndRenderPass(*m_device, *m_cmdBuffer, m_parameters.renderingType);
2391 
2392     afterRenderPass();
2393 
2394     VK_CHECK(m_device->endCommandBuffer(*m_cmdBuffer));
2395     submitCommandsAndWait(*m_device, *m_logicalDevice, m_queue, *m_cmdBuffer);
2396 }
2397 
2398 class MultiViewClearAttachmentsTestInstance : public MultiViewRenderTestInstance
2399 {
2400 public:
2401     MultiViewClearAttachmentsTestInstance(Context &context, const TestParameters &parameters);
2402 
2403 protected:
2404     void draw(const uint32_t subpassCount, VkRenderPass renderPass, VkFramebuffer frameBuffer,
2405               vector<PipelineSp> &pipelines);
2406 };
2407 
MultiViewClearAttachmentsTestInstance(Context & context,const TestParameters & parameters)2408 MultiViewClearAttachmentsTestInstance::MultiViewClearAttachmentsTestInstance(Context &context,
2409                                                                              const TestParameters &parameters)
2410     : MultiViewRenderTestInstance(context, parameters)
2411 {
2412 }
2413 
draw(const uint32_t subpassCount,VkRenderPass renderPass,VkFramebuffer frameBuffer,vector<PipelineSp> & pipelines)2414 void MultiViewClearAttachmentsTestInstance::draw(const uint32_t subpassCount, VkRenderPass renderPass,
2415                                                  VkFramebuffer frameBuffer, vector<PipelineSp> &pipelines)
2416 {
2417     const VkRect2D renderArea                = {{0, 0}, {m_parameters.extent.width, m_parameters.extent.height}};
2418     const VkClearValue renderPassClearValue  = makeClearValueColor(tcu::Vec4(0.0f));
2419     const VkBuffer vertexBuffers[]           = {*m_vertexCoordBuffer, *m_vertexColorBuffer};
2420     const VkDeviceSize vertexBufferOffsets[] = {0u, 0u};
2421     const uint32_t drawCountPerSubpass       = (subpassCount == 1) ? m_squareCount : 1u;
2422 
2423     beginCommandBuffer(*m_device, *m_cmdBuffer);
2424 
2425     beforeRenderPass();
2426 
2427     if (!m_useDynamicRendering)
2428     {
2429         const VkRenderPassBeginInfo renderPassBeginInfo{
2430             VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
2431             DE_NULL,                                  // const void* pNext;
2432             renderPass,                               // VkRenderPass renderPass;
2433             frameBuffer,                              // VkFramebuffer framebuffer;
2434             renderArea,                               // VkRect2D renderArea;
2435             1u,                                       // uint32_t clearValueCount;
2436             &renderPassClearValue,                    // const VkClearValue* pClearValues;
2437         };
2438         cmdBeginRenderPass(*m_device, *m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE,
2439                            m_parameters.renderingType);
2440     }
2441 
2442     for (uint32_t subpassNdx = 0u; subpassNdx < subpassCount; subpassNdx++)
2443     {
2444         VkClearAttachment clearAttachment = {
2445             VK_IMAGE_ASPECT_COLOR_BIT,                             // VkImageAspectFlags    aspectMask
2446             0u,                                                    // uint32_t                colorAttachment
2447             makeClearValueColor(tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)) // VkClearValue            clearValue
2448         };
2449 
2450         const VkOffset2D offset[2] = {{0, 0},
2451                                       {static_cast<int32_t>(static_cast<float>(m_parameters.extent.width) * 0.25f),
2452                                        static_cast<int32_t>(static_cast<float>(m_parameters.extent.height) * 0.25f)}};
2453 
2454         const VkExtent2D extent[2] = {{m_parameters.extent.width, m_parameters.extent.height},
2455                                       {static_cast<uint32_t>(static_cast<float>(m_parameters.extent.width) * 0.5f),
2456                                        static_cast<uint32_t>(static_cast<float>(m_parameters.extent.height) * 0.5f)}};
2457 
2458         const VkRect2D rect2D[2] = {{offset[0], extent[0]}, {offset[1], extent[1]}};
2459 
2460         VkClearRect clearRect = {
2461             rect2D[0], // VkRect2D    rect
2462             0u,        // uint32_t    baseArrayLayer
2463             1u,        // uint32_t    layerCount
2464         };
2465 
2466 #ifndef CTS_USES_VULKANSC
2467         if (m_useDynamicRendering)
2468         {
2469             addRenderingSubpassDependencyIfRequired(subpassNdx);
2470 
2471             beginRendering(*m_device, *m_cmdBuffer, m_colorAttachment->getImageView(), renderArea, renderPassClearValue,
2472                            VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
2473                            (subpassNdx ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_CLEAR), 0u,
2474                            m_parameters.extent.depth, m_parameters.viewMasks[subpassNdx]);
2475         }
2476 #endif // CTS_USES_VULKANSC
2477 
2478         m_device->cmdClearAttachments(*m_cmdBuffer, 1u, &clearAttachment, 1u, &clearRect);
2479         m_device->cmdBindVertexBuffers(*m_cmdBuffer, 0u, DE_LENGTH_OF_ARRAY(vertexBuffers), vertexBuffers,
2480                                        vertexBufferOffsets);
2481         m_device->cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipelines[subpassNdx]);
2482 
2483         for (uint32_t drawNdx = 0u; drawNdx < drawCountPerSubpass; ++drawNdx)
2484             m_device->cmdDraw(*m_cmdBuffer, 4u, 1u, (drawNdx + subpassNdx % m_squareCount) * 4u, 0u);
2485 
2486         clearRect.rect             = rect2D[1];
2487         clearAttachment.clearValue = makeClearValueColor(tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f));
2488         m_device->cmdClearAttachments(*m_cmdBuffer, 1u, &clearAttachment, 1u, &clearRect);
2489 
2490 #ifndef CTS_USES_VULKANSC
2491         if (m_useDynamicRendering)
2492             endRendering(*m_device, *m_cmdBuffer);
2493         else
2494 #endif // CTS_USES_VULKANSC
2495             if (subpassNdx < subpassCount - 1u)
2496                 cmdNextSubpass(*m_device, *m_cmdBuffer, VK_SUBPASS_CONTENTS_INLINE, m_parameters.renderingType);
2497     }
2498 
2499     if (!m_useDynamicRendering)
2500         cmdEndRenderPass(*m_device, *m_cmdBuffer, m_parameters.renderingType);
2501 
2502     afterRenderPass();
2503 
2504     VK_CHECK(m_device->endCommandBuffer(*m_cmdBuffer));
2505     submitCommandsAndWait(*m_device, *m_logicalDevice, m_queue, *m_cmdBuffer);
2506 }
2507 
2508 class MultiViewSecondaryCommandBufferTestInstance : public MultiViewRenderTestInstance
2509 {
2510 public:
2511     MultiViewSecondaryCommandBufferTestInstance(Context &context, const TestParameters &parameters);
2512 
2513 protected:
2514     void draw(const uint32_t subpassCount, VkRenderPass renderPass, VkFramebuffer frameBuffer,
2515               vector<PipelineSp> &pipelines);
2516 };
2517 
MultiViewSecondaryCommandBufferTestInstance(Context & context,const TestParameters & parameters)2518 MultiViewSecondaryCommandBufferTestInstance::MultiViewSecondaryCommandBufferTestInstance(
2519     Context &context, const TestParameters &parameters)
2520     : MultiViewRenderTestInstance(context, parameters)
2521 {
2522     if (TEST_TYPE_NESTED_CMD_BUFFER == parameters.viewIndex)
2523     {
2524         context.requireDeviceFunctionality("VK_EXT_nested_command_buffer");
2525 #ifndef CTS_USES_VULKANSC
2526         const auto &features =
2527             *findStructure<VkPhysicalDeviceNestedCommandBufferFeaturesEXT>(&context.getDeviceFeatures2());
2528         if (!features.nestedCommandBuffer)
2529 #endif // CTS_USES_VULKANSC
2530             TCU_THROW(NotSupportedError, "nestedCommandBuffer is not supported");
2531 #ifndef CTS_USES_VULKANSC
2532         if (!features.nestedCommandBufferRendering)
2533 #endif // CTS_USES_VULKANSC
2534             TCU_THROW(NotSupportedError, "nestedCommandBufferRendering is not supported");
2535     }
2536 }
2537 
draw(const uint32_t subpassCount,VkRenderPass renderPass,VkFramebuffer frameBuffer,vector<PipelineSp> & pipelines)2538 void MultiViewSecondaryCommandBufferTestInstance::draw(const uint32_t subpassCount, VkRenderPass renderPass,
2539                                                        VkFramebuffer frameBuffer, vector<PipelineSp> &pipelines)
2540 {
2541     typedef de::SharedPtr<Unique<VkCommandBuffer>> VkCommandBufferSp;
2542 
2543     createSecondaryCommandPool();
2544 
2545     const VkRect2D renderArea                = {{0, 0}, {m_parameters.extent.width, m_parameters.extent.height}};
2546     const VkClearValue renderPassClearValue  = makeClearValueColor(tcu::Vec4(0.0f));
2547     const VkBuffer vertexBuffers[]           = {*m_vertexCoordBuffer, *m_vertexColorBuffer};
2548     const VkDeviceSize vertexBufferOffsets[] = {0u, 0u};
2549     const uint32_t drawCountPerSubpass       = (subpassCount == 1) ? m_squareCount : 1u;
2550 
2551     beginCommandBuffer(*m_device, *m_cmdBuffer);
2552 
2553     beforeRenderPass();
2554 
2555     const VkRenderPassBeginInfo renderPassBeginInfo{
2556         VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
2557         DE_NULL,                                  // const void* pNext;
2558         renderPass,                               // VkRenderPass renderPass;
2559         frameBuffer,                              // VkFramebuffer framebuffer;
2560         renderArea,                               // VkRect2D renderArea;
2561         1u,                                       // uint32_t clearValueCount;
2562         &renderPassClearValue,                    // const VkClearValue* pClearValues;
2563     };
2564     if (!m_useDynamicRendering)
2565         cmdBeginRenderPass(*m_device, *m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS,
2566                            m_parameters.renderingType);
2567 
2568     //Create secondary buffer
2569     const VkCommandBufferAllocateInfo cmdBufferAllocateInfo = {
2570         VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
2571         DE_NULL,                                        // const void* pNext;
2572         *m_cmdPoolSecondary,                            // VkCommandPool commandPool;
2573         VK_COMMAND_BUFFER_LEVEL_SECONDARY,              // VkCommandBufferLevel level;
2574         1u,                                             // uint32_t bufferCount;
2575     };
2576     vector<VkCommandBufferSp> cmdBufferSecondary;
2577     vector<VkCommandBufferSp> cmdBufferNested;
2578 
2579     for (uint32_t subpassNdx = 0u; subpassNdx < subpassCount; subpassNdx++)
2580     {
2581         if (TEST_TYPE_NESTED_CMD_BUFFER == m_parameters.viewIndex)
2582         {
2583             cmdBufferNested.push_back(VkCommandBufferSp(new Unique<VkCommandBuffer>(
2584                 allocateCommandBuffer(*m_device, *m_logicalDevice, &cmdBufferAllocateInfo))));
2585         }
2586         cmdBufferSecondary.push_back(VkCommandBufferSp(
2587             new Unique<VkCommandBuffer>(allocateCommandBuffer(*m_device, *m_logicalDevice, &cmdBufferAllocateInfo))));
2588 
2589 #ifndef CTS_USES_VULKANSC
2590         const VkCommandBufferInheritanceRenderingInfoKHR secCmdBufInheritRenderingInfo{
2591             VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR, // VkStructureType sType;
2592             DE_NULL,                                                         // const void* pNext;
2593             0u,                                                              // VkRenderingFlagsKHR flags;
2594             m_parameters.viewMasks[subpassNdx],                              // uint32_t viewMask;
2595             1u,                                                              // uint32_t colorAttachmentCount;
2596             &m_parameters.colorFormat,                                       // const VkFormat* pColorAttachmentFormats;
2597             VK_FORMAT_UNDEFINED,                                             // VkFormat depthAttachmentFormat;
2598             VK_FORMAT_UNDEFINED,                                             // VkFormat stencilAttachmentFormat;
2599             m_parameters.samples // VkSampleCountFlagBits rasterizationSamples;
2600         };
2601 #endif // CTS_USES_VULKANSC
2602 
2603         const VkCommandBufferInheritanceInfo secCmdBufInheritInfo{
2604             VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, // VkStructureType sType;
2605 #ifndef CTS_USES_VULKANSC
2606             m_useDynamicRendering ? &secCmdBufInheritRenderingInfo : DE_NULL, // const void* pNext;
2607 #else
2608             DE_NULL, // const void* pNext;
2609 #endif                                         // CTS_USES_VULKANSC
2610             renderPass,                        // VkRenderPass renderPass;
2611             subpassNdx,                        // uint32_t subpass;
2612             frameBuffer,                       // VkFramebuffer framebuffer;
2613             VK_FALSE,                          // VkBool32 occlusionQueryEnable;
2614             (VkQueryControlFlags)0u,           // VkQueryControlFlags queryFlags;
2615             (VkQueryPipelineStatisticFlags)0u, // VkQueryPipelineStatisticFlags pipelineStatistics;
2616         };
2617 
2618         const VkCommandBufferBeginInfo info{
2619             VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,      // VkStructureType sType;
2620             DE_NULL,                                          // const void* pNext;
2621             VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, // VkCommandBufferUsageFlags flags;
2622             &secCmdBufInheritInfo,                            // const VkCommandBufferInheritanceInfo* pInheritanceInfo;
2623         };
2624 
2625         if (TEST_TYPE_NESTED_CMD_BUFFER == m_parameters.viewIndex)
2626         {
2627             VK_CHECK(m_device->beginCommandBuffer(cmdBufferNested.back().get()->get(), &info));
2628         }
2629 
2630         VK_CHECK(m_device->beginCommandBuffer(cmdBufferSecondary.back().get()->get(), &info));
2631 
2632         m_device->cmdBindVertexBuffers(cmdBufferSecondary.back().get()->get(), 0u, DE_LENGTH_OF_ARRAY(vertexBuffers),
2633                                        vertexBuffers, vertexBufferOffsets);
2634         m_device->cmdBindPipeline(cmdBufferSecondary.back().get()->get(), VK_PIPELINE_BIND_POINT_GRAPHICS,
2635                                   **pipelines[subpassNdx]);
2636 
2637 #ifndef CTS_USES_VULKANSC
2638         if (m_useDynamicRendering)
2639         {
2640             addRenderingSubpassDependencyIfRequired(subpassNdx);
2641 
2642             beginRendering(*m_device, *m_cmdBuffer, m_colorAttachment->getImageView(), renderArea, renderPassClearValue,
2643                            VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
2644                            (subpassNdx ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_CLEAR),
2645                            VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT_KHR, m_parameters.extent.depth,
2646                            m_parameters.viewMasks[subpassNdx]);
2647         }
2648 #endif // CTS_USES_VULKANSC
2649 
2650         for (uint32_t drawNdx = 0u; drawNdx < drawCountPerSubpass; ++drawNdx)
2651             m_device->cmdDraw(cmdBufferSecondary.back().get()->get(), 4u, 1u,
2652                               (drawNdx + subpassNdx % m_squareCount) * 4u, 0u);
2653 
2654         VK_CHECK(m_device->endCommandBuffer(cmdBufferSecondary.back().get()->get()));
2655 
2656         if (TEST_TYPE_NESTED_CMD_BUFFER == m_parameters.viewIndex)
2657         {
2658             m_device->cmdExecuteCommands(cmdBufferNested.back().get()->get(), 1u,
2659                                          &cmdBufferSecondary.back().get()->get());
2660             VK_CHECK(m_device->endCommandBuffer(cmdBufferNested.back().get()->get()));
2661             m_device->cmdExecuteCommands(*m_cmdBuffer, 1u, &cmdBufferNested.back().get()->get());
2662         }
2663         else
2664         {
2665             m_device->cmdExecuteCommands(*m_cmdBuffer, 1u, &cmdBufferSecondary.back().get()->get());
2666         }
2667 
2668 #ifndef CTS_USES_VULKANSC
2669         if (m_useDynamicRendering)
2670             endRendering(*m_device, *m_cmdBuffer);
2671         else
2672 #endif // CTS_USES_VULKANSC
2673             if (subpassNdx < subpassCount - 1u)
2674                 cmdNextSubpass(*m_device, *m_cmdBuffer, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS,
2675                                m_parameters.renderingType);
2676     }
2677 
2678     if (!m_useDynamicRendering)
2679         cmdEndRenderPass(*m_device, *m_cmdBuffer, m_parameters.renderingType);
2680 
2681     afterRenderPass();
2682 
2683     VK_CHECK(m_device->endCommandBuffer(*m_cmdBuffer));
2684     submitCommandsAndWait(*m_device, *m_logicalDevice, m_queue, *m_cmdBuffer);
2685 }
2686 
2687 class MultiViewPointSizeTestInstance : public MultiViewRenderTestInstance
2688 {
2689 public:
2690     MultiViewPointSizeTestInstance(Context &context, const TestParameters &parameters);
2691 
2692 protected:
2693     void validatePointSize(const VkPhysicalDeviceLimits &limits, const uint32_t pointSize);
2694     void createVertexData(void);
2695     void draw(const uint32_t subpassCount, VkRenderPass renderPass, VkFramebuffer frameBuffer,
2696               vector<PipelineSp> &pipelines);
2697 };
2698 
MultiViewPointSizeTestInstance(Context & context,const TestParameters & parameters)2699 MultiViewPointSizeTestInstance::MultiViewPointSizeTestInstance(Context &context, const TestParameters &parameters)
2700     : MultiViewRenderTestInstance(context, parameters)
2701 {
2702     const auto &vki                     = m_context.getInstanceInterface();
2703     const auto physDevice               = m_context.getPhysicalDevice();
2704     const VkPhysicalDeviceLimits limits = getPhysicalDeviceProperties(vki, physDevice).limits;
2705 
2706     validatePointSize(limits, static_cast<uint32_t>(TEST_POINT_SIZE_WIDE));
2707     validatePointSize(limits, static_cast<uint32_t>(TEST_POINT_SIZE_SMALL));
2708 }
2709 
validatePointSize(const VkPhysicalDeviceLimits & limits,const uint32_t pointSize)2710 void MultiViewPointSizeTestInstance::validatePointSize(const VkPhysicalDeviceLimits &limits, const uint32_t pointSize)
2711 {
2712     const float testPointSizeFloat = static_cast<float>(pointSize);
2713     float granuleCount             = 0.0f;
2714 
2715     if (!de::inRange(testPointSizeFloat, limits.pointSizeRange[0], limits.pointSizeRange[1]))
2716         TCU_THROW(NotSupportedError, "Required point size is outside of the the limits range");
2717 
2718     granuleCount = static_cast<float>(
2719         deCeilFloatToInt32((testPointSizeFloat - limits.pointSizeRange[0]) / limits.pointSizeGranularity));
2720 
2721     if (limits.pointSizeRange[0] + granuleCount * limits.pointSizeGranularity != testPointSizeFloat)
2722         TCU_THROW(NotSupportedError, "Granuliraty does not allow to get required point size");
2723 
2724     DE_ASSERT(pointSize + 1 <= m_parameters.extent.width / 2);
2725     DE_ASSERT(pointSize + 1 <= m_parameters.extent.height / 2);
2726 }
2727 
createVertexData(void)2728 void MultiViewPointSizeTestInstance::createVertexData(void)
2729 {
2730     const float pixelStepX = 2.0f / static_cast<float>(m_parameters.extent.width);
2731     const float pixelStepY = 2.0f / static_cast<float>(m_parameters.extent.height);
2732     const int pointMargin  = 1 + TEST_POINT_SIZE_WIDE / 2;
2733 
2734     appendVertex(tcu::Vec4(-1.0f + pointMargin * pixelStepX, -1.0f + pointMargin * pixelStepY, 1.0f, 1.0f),
2735                  tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
2736     appendVertex(tcu::Vec4(-1.0f + pointMargin * pixelStepX, 0.0f + pointMargin * pixelStepY, 1.0f, 1.0f),
2737                  tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f));
2738     appendVertex(tcu::Vec4(0.0f + pointMargin * pixelStepX, -1.0f + pointMargin * pixelStepY, 1.0f, 1.0f),
2739                  tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f));
2740     appendVertex(tcu::Vec4(0.0f + pointMargin * pixelStepX, 0.0f + pointMargin * pixelStepY, 1.0f, 1.0f),
2741                  tcu::Vec4(1.0f, 0.5f, 0.3f, 1.0f));
2742 }
2743 
draw(const uint32_t subpassCount,VkRenderPass renderPass,VkFramebuffer frameBuffer,vector<PipelineSp> & pipelines)2744 void MultiViewPointSizeTestInstance::draw(const uint32_t subpassCount, VkRenderPass renderPass,
2745                                           VkFramebuffer frameBuffer, vector<PipelineSp> &pipelines)
2746 {
2747     const VkRect2D renderArea                = {{0, 0}, {m_parameters.extent.width, m_parameters.extent.height}};
2748     const VkClearValue renderPassClearValue  = makeClearValueColor(tcu::Vec4(0.0f));
2749     const VkBuffer vertexBuffers[]           = {*m_vertexCoordBuffer, *m_vertexColorBuffer};
2750     const VkDeviceSize vertexBufferOffsets[] = {0u, 0u};
2751     const uint32_t drawCountPerSubpass       = (subpassCount == 1) ? m_squareCount : 1u;
2752 
2753     beginCommandBuffer(*m_device, *m_cmdBuffer);
2754 
2755     beforeRenderPass();
2756 
2757     if (!m_useDynamicRendering)
2758     {
2759         const VkRenderPassBeginInfo renderPassBeginInfo{
2760             VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
2761             DE_NULL,                                  // const void* pNext;
2762             renderPass,                               // VkRenderPass renderPass;
2763             frameBuffer,                              // VkFramebuffer framebuffer;
2764             renderArea,                               // VkRect2D renderArea;
2765             1u,                                       // uint32_t clearValueCount;
2766             &renderPassClearValue,                    // const VkClearValue* pClearValues;
2767         };
2768         cmdBeginRenderPass(*m_device, *m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE,
2769                            m_parameters.renderingType);
2770     }
2771 
2772     for (uint32_t subpassNdx = 0u; subpassNdx < subpassCount; subpassNdx++)
2773     {
2774         m_device->cmdBindVertexBuffers(*m_cmdBuffer, 0u, DE_LENGTH_OF_ARRAY(vertexBuffers), vertexBuffers,
2775                                        vertexBufferOffsets);
2776 
2777         m_device->cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipelines[subpassNdx]);
2778 
2779 #ifndef CTS_USES_VULKANSC
2780         if (m_useDynamicRendering)
2781         {
2782             addRenderingSubpassDependencyIfRequired(subpassNdx);
2783 
2784             beginRendering(*m_device, *m_cmdBuffer, m_colorAttachment->getImageView(), renderArea, renderPassClearValue,
2785                            VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
2786                            (subpassNdx ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_CLEAR), 0u,
2787                            m_parameters.extent.depth, m_parameters.viewMasks[subpassNdx]);
2788         }
2789 #endif // CTS_USES_VULKANSC
2790 
2791         for (uint32_t drawNdx = 0u; drawNdx < drawCountPerSubpass; ++drawNdx)
2792             m_device->cmdDraw(*m_cmdBuffer, 1u, 1u, drawNdx + subpassNdx % m_squareCount, 0u);
2793 
2794 #ifndef CTS_USES_VULKANSC
2795         if (m_useDynamicRendering)
2796             endRendering(*m_device, *m_cmdBuffer);
2797         else
2798 #endif // CTS_USES_VULKANSC
2799             if (subpassNdx < subpassCount - 1u)
2800                 cmdNextSubpass(*m_device, *m_cmdBuffer, VK_SUBPASS_CONTENTS_INLINE, m_parameters.renderingType);
2801     }
2802 
2803     if (!m_useDynamicRendering)
2804         cmdEndRenderPass(*m_device, *m_cmdBuffer, m_parameters.renderingType);
2805 
2806     afterRenderPass();
2807 
2808     VK_CHECK(m_device->endCommandBuffer(*m_cmdBuffer));
2809     submitCommandsAndWait(*m_device, *m_logicalDevice, m_queue, *m_cmdBuffer);
2810 }
2811 
2812 class MultiViewMultsampleTestInstance : public MultiViewRenderTestInstance
2813 {
2814 public:
2815     MultiViewMultsampleTestInstance(Context &context, const TestParameters &parameters);
2816 
2817 protected:
2818     tcu::TestStatus iterate(void);
2819     void createVertexData(void);
2820 
2821     void draw(const uint32_t subpassCount, VkRenderPass renderPass, VkFramebuffer frameBuffer,
2822               vector<PipelineSp> &pipelines);
2823     void afterRenderPass(void);
2824 
2825 private:
2826     de::SharedPtr<ImageAttachment> m_resolveAttachment;
2827 };
2828 
MultiViewMultsampleTestInstance(Context & context,const TestParameters & parameters)2829 MultiViewMultsampleTestInstance::MultiViewMultsampleTestInstance(Context &context, const TestParameters &parameters)
2830     : MultiViewRenderTestInstance(context, parameters)
2831 {
2832     // Color attachment
2833     m_resolveAttachment = de::SharedPtr<ImageAttachment>(
2834         new ImageAttachment(*m_logicalDevice, *m_device, *m_allocator, m_parameters.extent, m_parameters.colorFormat,
2835                             VK_SAMPLE_COUNT_1_BIT));
2836 }
2837 
iterate(void)2838 tcu::TestStatus MultiViewMultsampleTestInstance::iterate(void)
2839 {
2840     const uint32_t subpassCount = static_cast<uint32_t>(m_parameters.viewMasks.size());
2841     Move<VkRenderPass> renderPass;
2842     Move<VkFramebuffer> frameBuffer;
2843 
2844     // FrameBuffer & renderPass
2845     if (m_parameters.renderingType != RENDERING_TYPE_DYNAMIC_RENDERING)
2846     {
2847         renderPass  = makeRenderPass(*m_device, *m_logicalDevice, m_parameters.colorFormat, m_parameters.viewMasks,
2848                                      m_parameters.renderingType, VK_SAMPLE_COUNT_4_BIT);
2849         frameBuffer = makeFramebuffer(*m_device, *m_logicalDevice, *renderPass, m_colorAttachment->getImageView(),
2850                                       m_parameters.extent.width, m_parameters.extent.height);
2851     }
2852 
2853     // pipelineLayout
2854     Unique<VkPipelineLayout> pipelineLayout(makePipelineLayout(*m_device, *m_logicalDevice));
2855 
2856     // pipelines
2857     map<VkShaderStageFlagBits, ShaderModuleSP> shaderModule;
2858     vector<PipelineSp> pipelines(subpassCount);
2859     const VkVertexInputRate vertexInputRate = (TEST_TYPE_INPUT_RATE_INSTANCE == m_parameters.viewIndex) ?
2860                                                   VK_VERTEX_INPUT_RATE_INSTANCE :
2861                                                   VK_VERTEX_INPUT_RATE_VERTEX;
2862 
2863     {
2864         vector<VkPipelineShaderStageCreateInfo> shaderStageParams;
2865         madeShaderModule(shaderModule, shaderStageParams);
2866         for (uint32_t subpassNdx = 0u; subpassNdx < subpassCount; ++subpassNdx)
2867             pipelines[subpassNdx] = (PipelineSp(new Unique<VkPipeline>(
2868                 makeGraphicsPipeline(*renderPass, *pipelineLayout, static_cast<uint32_t>(shaderStageParams.size()),
2869                                      shaderStageParams.data(), subpassNdx, vertexInputRate))));
2870     }
2871 
2872     createCommandBuffer();
2873     createVertexData();
2874     createVertexBuffer();
2875 
2876     draw(subpassCount, *renderPass, *frameBuffer, pipelines);
2877 
2878     {
2879         vector<uint8_t> pixelAccessData(m_parameters.extent.width * m_parameters.extent.height *
2880                                         m_parameters.extent.depth *
2881                                         mapVkFormat(m_parameters.colorFormat).getPixelSize());
2882         tcu::PixelBufferAccess dst(mapVkFormat(m_parameters.colorFormat), m_parameters.extent.width,
2883                                    m_parameters.extent.height, m_parameters.extent.depth, pixelAccessData.data());
2884 
2885         readImage(m_resolveAttachment->getImage(), dst);
2886 
2887         if (!checkImage(dst))
2888             return tcu::TestStatus::fail("Fail");
2889     }
2890 
2891     return tcu::TestStatus::pass("Pass");
2892 }
2893 
createVertexData(void)2894 void MultiViewMultsampleTestInstance::createVertexData(void)
2895 {
2896     tcu::Vec4 color = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
2897 
2898     color = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
2899     appendVertex(tcu::Vec4(-1.0f, 0.0f, 1.0f, 1.0f), color);
2900     appendVertex(tcu::Vec4(-1.0f, -1.0f, 1.0f, 1.0f), color);
2901     appendVertex(tcu::Vec4(0.0f, -1.0f, 1.0f, 1.0f), color);
2902 
2903     color = tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f);
2904     appendVertex(tcu::Vec4(-1.0f, 1.0f, 1.0f, 1.0f), color);
2905     appendVertex(tcu::Vec4(-1.0f, 0.0f, 1.0f, 1.0f), color);
2906     appendVertex(tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), color);
2907 
2908     color = tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f);
2909     appendVertex(tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), color);
2910     appendVertex(tcu::Vec4(0.0f, -1.0f, 1.0f, 1.0f), color);
2911     appendVertex(tcu::Vec4(1.0f, -1.0f, 1.0f, 1.0f), color);
2912 
2913     color = tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f);
2914     appendVertex(tcu::Vec4(0.0f, 1.0f, 1.0f, 1.0f), color);
2915     appendVertex(tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), color);
2916     appendVertex(tcu::Vec4(1.0f, 0.0f, 1.0f, 1.0f), color);
2917 }
2918 
draw(const uint32_t subpassCount,VkRenderPass renderPass,VkFramebuffer frameBuffer,vector<PipelineSp> & pipelines)2919 void MultiViewMultsampleTestInstance::draw(const uint32_t subpassCount, VkRenderPass renderPass,
2920                                            VkFramebuffer frameBuffer, vector<PipelineSp> &pipelines)
2921 {
2922     const VkRect2D renderArea                       = {{0, 0}, {m_parameters.extent.width, m_parameters.extent.height}};
2923     const VkClearValue renderPassClearValue         = makeClearValueColor(tcu::Vec4(0.0f));
2924     const VkBuffer vertexBuffers[]                  = {*m_vertexCoordBuffer, *m_vertexColorBuffer};
2925     const VkDeviceSize vertexBufferOffsets[]        = {0u, 0u};
2926     const uint32_t drawCountPerSubpass              = (subpassCount == 1) ? m_squareCount : 1u;
2927     const uint32_t vertexPerPrimitive               = 3u;
2928     const VkImageSubresourceLayers subresourceLayer = {
2929         VK_IMAGE_ASPECT_COLOR_BIT, //  VkImageAspectFlags aspectMask;
2930         0u,                        //  uint32_t mipLevel;
2931         0u,                        //  uint32_t baseArrayLayer;
2932         m_parameters.extent.depth, //  uint32_t layerCount;
2933     };
2934     const VkImageResolve imageResolveRegion = {
2935         subresourceLayer,      //  VkImageSubresourceLayers srcSubresource;
2936         makeOffset3D(0, 0, 0), //  VkOffset3D srcOffset;
2937         subresourceLayer,      //  VkImageSubresourceLayers dstSubresource;
2938         makeOffset3D(0, 0, 0), //  VkOffset3D dstOffset;
2939         makeExtent3D(m_parameters.extent.width, m_parameters.extent.height, 1u), //  VkExtent3D extent;
2940     };
2941 
2942     beginCommandBuffer(*m_device, *m_cmdBuffer);
2943 
2944     beforeRenderPass();
2945 
2946     if (!m_useDynamicRendering)
2947     {
2948         const VkRenderPassBeginInfo renderPassBeginInfo{
2949             VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
2950             DE_NULL,                                  // const void* pNext;
2951             renderPass,                               // VkRenderPass renderPass;
2952             frameBuffer,                              // VkFramebuffer framebuffer;
2953             renderArea,                               // VkRect2D renderArea;
2954             1u,                                       // uint32_t clearValueCount;
2955             &renderPassClearValue,                    // const VkClearValue* pClearValues;
2956         };
2957         cmdBeginRenderPass(*m_device, *m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE,
2958                            m_parameters.renderingType);
2959     }
2960 
2961     for (uint32_t subpassNdx = 0u; subpassNdx < subpassCount; subpassNdx++)
2962     {
2963         m_device->cmdBindVertexBuffers(*m_cmdBuffer, 0u, DE_LENGTH_OF_ARRAY(vertexBuffers), vertexBuffers,
2964                                        vertexBufferOffsets);
2965 
2966         m_device->cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipelines[subpassNdx]);
2967 
2968 #ifndef CTS_USES_VULKANSC
2969         if (m_useDynamicRendering)
2970         {
2971             addRenderingSubpassDependencyIfRequired(subpassNdx);
2972 
2973             beginRendering(*m_device, *m_cmdBuffer, m_colorAttachment->getImageView(), renderArea, renderPassClearValue,
2974                            VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
2975                            (subpassNdx ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_CLEAR), 0u,
2976                            m_parameters.extent.depth, m_parameters.viewMasks[subpassNdx]);
2977         }
2978 #endif // CTS_USES_VULKANSC
2979 
2980         for (uint32_t drawNdx = 0u; drawNdx < drawCountPerSubpass; ++drawNdx)
2981             m_device->cmdDraw(*m_cmdBuffer, vertexPerPrimitive, 1u,
2982                               (drawNdx + subpassNdx % m_squareCount) * vertexPerPrimitive, 0u);
2983 
2984 #ifndef CTS_USES_VULKANSC
2985         if (m_useDynamicRendering)
2986             endRendering(*m_device, *m_cmdBuffer);
2987         else
2988 #endif // CTS_USES_VULKANSC
2989             if (subpassNdx < subpassCount - 1u)
2990                 cmdNextSubpass(*m_device, *m_cmdBuffer, VK_SUBPASS_CONTENTS_INLINE, m_parameters.renderingType);
2991     }
2992 
2993     if (!m_useDynamicRendering)
2994         cmdEndRenderPass(*m_device, *m_cmdBuffer, m_parameters.renderingType);
2995 
2996     afterRenderPass();
2997 
2998     m_device->cmdResolveImage(*m_cmdBuffer, m_colorAttachment->getImage(), VK_IMAGE_LAYOUT_GENERAL,
2999                               m_resolveAttachment->getImage(), VK_IMAGE_LAYOUT_GENERAL, 1u, &imageResolveRegion);
3000 
3001     VK_CHECK(m_device->endCommandBuffer(*m_cmdBuffer));
3002     submitCommandsAndWait(*m_device, *m_logicalDevice, m_queue, *m_cmdBuffer);
3003 }
3004 
afterRenderPass(void)3005 void MultiViewMultsampleTestInstance::afterRenderPass(void)
3006 {
3007     const VkImageSubresourceRange subresourceRange = {
3008         VK_IMAGE_ASPECT_COLOR_BIT, //  VkImageAspectFlags aspectMask;
3009         0u,                        //  uint32_t baseMipLevel;
3010         1u,                        //  uint32_t levelCount;
3011         0u,                        //  uint32_t baseArrayLayer;
3012         m_parameters.extent.depth, //  uint32_t layerCount;
3013     };
3014 
3015     imageBarrier(*m_device, *m_cmdBuffer, m_colorAttachment->getImage(), subresourceRange,
3016                  VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL,
3017                  VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
3018                  VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
3019 
3020     imageBarrier(*m_device, *m_cmdBuffer, m_resolveAttachment->getImage(), subresourceRange, VK_IMAGE_LAYOUT_UNDEFINED,
3021                  VK_IMAGE_LAYOUT_GENERAL, 0u, VK_ACCESS_TRANSFER_WRITE_BIT,
3022                  VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
3023 }
3024 
3025 class MultiViewQueriesTestInstance : public MultiViewRenderTestInstance
3026 {
3027 public:
3028     MultiViewQueriesTestInstance(Context &context, const TestParameters &parameters);
3029 
3030 protected:
3031     tcu::TestStatus iterate(void);
3032     void createVertexData(void);
3033 
3034     void draw(const uint32_t subpassCount, VkRenderPass renderPass, VkFramebuffer frameBuffer,
3035               vector<PipelineSp> &pipelines);
3036     uint32_t getUsedViewsCount(const uint32_t viewMaskIndex);
3037     uint32_t getQueryCountersNumber();
3038 
3039 private:
3040     const uint32_t m_verticesPerPrimitive;
3041     const VkQueryControlFlags m_occlusionQueryFlags;
3042     uint64_t m_timestampMask;
3043     vector<uint64_t> m_timestampStartValues;
3044     vector<uint64_t> m_timestampEndValues;
3045     vector<uint64_t> m_timestampStartAvailabilityValues;
3046     vector<uint64_t> m_timestampEndAvailabilityValues;
3047     vector<bool> m_counterSeriesStart;
3048     vector<bool> m_counterSeriesEnd;
3049     vector<uint64_t> m_occlusionValues;
3050     vector<uint64_t> m_occlusionExpectedValues;
3051     vector<uint64_t> m_occlusionAvailabilityValues;
3052     uint32_t m_occlusionObjectsOffset;
3053     vector<uint64_t> m_occlusionObjectPixelsCount;
3054 };
3055 
MultiViewQueriesTestInstance(Context & context,const TestParameters & parameters)3056 MultiViewQueriesTestInstance::MultiViewQueriesTestInstance(Context &context, const TestParameters &parameters)
3057     : MultiViewRenderTestInstance(context, parameters)
3058     , m_verticesPerPrimitive(4u)
3059     , m_occlusionQueryFlags((parameters.viewIndex == TEST_TYPE_QUERIES) * VK_QUERY_CONTROL_PRECISE_BIT)
3060     , m_occlusionObjectsOffset(0)
3061 {
3062     // Generate the timestamp mask
3063     const auto &vki           = m_context.getInstanceInterface();
3064     const auto physicalDevice = m_context.getPhysicalDevice();
3065 
3066     const std::vector<VkQueueFamilyProperties> queueProperties =
3067         vk::getPhysicalDeviceQueueFamilyProperties(vki, physicalDevice);
3068 
3069     if (queueProperties[0].timestampValidBits == 0)
3070         TCU_THROW(NotSupportedError, "Device does not support timestamp.");
3071 
3072     m_timestampMask = 0xFFFFFFFFFFFFFFFFull >> (64 - queueProperties[0].timestampValidBits);
3073 }
3074 
verifyAvailabilityBits(const std::vector<uint64_t> & bits,const char * setName)3075 void verifyAvailabilityBits(const std::vector<uint64_t> &bits, const char *setName)
3076 {
3077     constexpr auto invalidValue = uint64_t{0};
3078     for (size_t i = 0u; i < bits.size(); ++i)
3079     {
3080         if (bits[i] == invalidValue)
3081             TCU_FAIL(setName + std::string(" availability bit ") + de::toString(i) + " is " +
3082                      de::toString(invalidValue));
3083     }
3084 }
3085 
iterate(void)3086 tcu::TestStatus MultiViewQueriesTestInstance::iterate(void)
3087 {
3088     const uint32_t subpassCount = static_cast<uint32_t>(m_parameters.viewMasks.size());
3089     Move<VkRenderPass> renderPass;
3090     Move<VkFramebuffer> frameBuffer;
3091     Unique<VkPipelineLayout> pipelineLayout(makePipelineLayout(*m_device, *m_logicalDevice));
3092     vector<PipelineSp> pipelines(subpassCount);
3093     uint64_t occlusionValue         = 0;
3094     uint64_t occlusionExpectedValue = 0;
3095     map<VkShaderStageFlagBits, ShaderModuleSP> shaderModule;
3096 
3097     if (m_parameters.renderingType != RENDERING_TYPE_DYNAMIC_RENDERING)
3098     {
3099         renderPass  = makeRenderPass(*m_device, *m_logicalDevice, m_parameters.colorFormat, m_parameters.viewMasks,
3100                                      m_parameters.renderingType);
3101         frameBuffer = makeFramebuffer(*m_device, *m_logicalDevice, *renderPass, m_colorAttachment->getImageView(),
3102                                       m_parameters.extent.width, m_parameters.extent.height);
3103     }
3104 
3105     {
3106         vector<VkPipelineShaderStageCreateInfo> shaderStageParams;
3107 
3108         madeShaderModule(shaderModule, shaderStageParams);
3109         for (uint32_t subpassNdx = 0u; subpassNdx < subpassCount; ++subpassNdx)
3110             pipelines[subpassNdx] = (PipelineSp(new Unique<VkPipeline>(
3111                 makeGraphicsPipeline(*renderPass, *pipelineLayout, static_cast<uint32_t>(shaderStageParams.size()),
3112                                      shaderStageParams.data(), subpassNdx))));
3113     }
3114 
3115     createCommandBuffer();
3116     createVertexData();
3117     createVertexBuffer();
3118 
3119     draw(subpassCount, *renderPass, *frameBuffer, pipelines);
3120 
3121     DE_ASSERT(!m_occlusionValues.empty());
3122     DE_ASSERT(m_occlusionValues.size() == m_occlusionExpectedValues.size());
3123     DE_ASSERT(m_occlusionValues.size() == m_counterSeriesEnd.size());
3124     for (size_t ndx = 0; ndx < m_counterSeriesEnd.size(); ++ndx)
3125     {
3126         occlusionValue += m_occlusionValues[ndx];
3127         occlusionExpectedValue += m_occlusionExpectedValues[ndx];
3128 
3129         if (m_counterSeriesEnd[ndx])
3130         {
3131             if (m_parameters.viewIndex == TEST_TYPE_QUERIES)
3132             {
3133                 if (occlusionExpectedValue != occlusionValue)
3134                     return tcu::TestStatus::fail("occlusion, result:" + de::toString(occlusionValue) +
3135                                                  ", expected:" + de::toString(occlusionExpectedValue));
3136             }
3137             else // verify non precise occlusion query
3138             {
3139                 if (occlusionValue == 0)
3140                     return tcu::TestStatus::fail("occlusion, result: 0, expected non zero value");
3141             }
3142         }
3143     }
3144     verifyAvailabilityBits(m_occlusionAvailabilityValues, "occlusion");
3145 
3146     DE_ASSERT(!m_timestampStartValues.empty());
3147     DE_ASSERT(m_timestampStartValues.size() == m_timestampEndValues.size());
3148     DE_ASSERT(m_timestampStartValues.size() == m_counterSeriesStart.size());
3149     for (size_t ndx = 0; ndx < m_timestampStartValues.size(); ++ndx)
3150     {
3151         if (m_counterSeriesStart[ndx])
3152         {
3153             if (m_timestampEndValues[ndx] > 0 && m_timestampEndValues[ndx] >= m_timestampStartValues[ndx])
3154                 continue;
3155         }
3156         else
3157         {
3158             if (m_timestampEndValues[ndx] > 0 && m_timestampEndValues[ndx] >= m_timestampStartValues[ndx])
3159                 continue;
3160 
3161             if (m_timestampEndValues[ndx] == 0 && m_timestampStartValues[ndx] == 0)
3162                 continue;
3163         }
3164 
3165         return tcu::TestStatus::fail("timestamp");
3166     }
3167     verifyAvailabilityBits(m_timestampStartAvailabilityValues, "timestamp start");
3168     verifyAvailabilityBits(m_timestampEndAvailabilityValues, "timestamp end");
3169 
3170     return tcu::TestStatus::pass("Pass");
3171 }
3172 
createVertexData(void)3173 void MultiViewQueriesTestInstance::createVertexData(void)
3174 {
3175     tcu::Vec4 color = tcu::Vec4(0.2f, 0.0f, 0.1f, 1.0f);
3176 
3177     appendVertex(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), color);
3178     appendVertex(tcu::Vec4(-1.0f, 0.0f, 0.0f, 1.0f), color);
3179     appendVertex(tcu::Vec4(0.0f, -1.0f, 0.0f, 1.0f), color);
3180     appendVertex(tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f), color);
3181 
3182     color = tcu::Vec4(0.3f, 0.0f, 0.2f, 1.0f);
3183     appendVertex(tcu::Vec4(-1.0f, 0.0f, 0.0f, 1.0f), color);
3184     appendVertex(tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f), color);
3185     appendVertex(tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f), color);
3186     appendVertex(tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f), color);
3187 
3188     color = tcu::Vec4(0.4f, 0.2f, 0.3f, 1.0f);
3189     appendVertex(tcu::Vec4(0.0f, -1.0f, 0.0f, 1.0f), color);
3190     appendVertex(tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f), color);
3191     appendVertex(tcu::Vec4(1.0f, -1.0f, 0.0f, 1.0f), color);
3192     appendVertex(tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), color);
3193 
3194     color = tcu::Vec4(0.5f, 0.0f, 0.4f, 1.0f);
3195     appendVertex(tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f), color);
3196     appendVertex(tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f), color);
3197     appendVertex(tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), color);
3198     appendVertex(tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f), color);
3199 
3200     // Create occluded square objects as zoom out of main
3201     const uint32_t mainObjectsVerticesCount     = static_cast<uint32_t>(m_vertexCoord.size());
3202     const uint32_t mainObjectsCount             = mainObjectsVerticesCount / m_verticesPerPrimitive;
3203     const uint32_t occlusionObjectMultiplierX[] = {1, 2, 2, 1};
3204     const uint32_t occlusionObjectMultiplierY[] = {1, 1, 3, 3};
3205     const uint32_t occlusionObjectDivisor       = 4u;
3206     const float occlusionObjectDivisorFloat     = static_cast<float>(occlusionObjectDivisor);
3207 
3208     DE_ASSERT(0 == m_parameters.extent.width % (2 * occlusionObjectDivisor));
3209     DE_ASSERT(0 == m_parameters.extent.height % (2 * occlusionObjectDivisor));
3210     DE_ASSERT(DE_LENGTH_OF_ARRAY(occlusionObjectMultiplierX) == mainObjectsCount);
3211     DE_ASSERT(DE_LENGTH_OF_ARRAY(occlusionObjectMultiplierY) == mainObjectsCount);
3212 
3213     for (size_t objectNdx = 0; objectNdx < mainObjectsCount; ++objectNdx)
3214     {
3215         const size_t objectStart = objectNdx * m_verticesPerPrimitive;
3216         const float xRatio = static_cast<float>(occlusionObjectMultiplierX[objectNdx]) / occlusionObjectDivisorFloat;
3217         const float yRatio = static_cast<float>(occlusionObjectMultiplierY[objectNdx]) / occlusionObjectDivisorFloat;
3218         const double areaRatio = static_cast<double>(xRatio) * static_cast<double>(yRatio);
3219         const uint64_t occludedPixelsCount =
3220             static_cast<uint64_t>(areaRatio * (m_parameters.extent.width / 2) * (m_parameters.extent.height / 2));
3221 
3222         m_occlusionObjectPixelsCount.push_back(occludedPixelsCount);
3223 
3224         for (size_t vertexNdx = 0; vertexNdx < m_verticesPerPrimitive; ++vertexNdx)
3225         {
3226             const float occludedObjectVertexXCoord = m_vertexCoord[objectStart + vertexNdx][0] * xRatio;
3227             const float occludedObjectVertexYCoord = m_vertexCoord[objectStart + vertexNdx][1] * yRatio;
3228             const tcu::Vec4 occludedObjectVertexCoord =
3229                 tcu::Vec4(occludedObjectVertexXCoord, occludedObjectVertexYCoord, 1.0f, 1.0f);
3230 
3231             appendVertex(occludedObjectVertexCoord, m_vertexColor[objectStart + vertexNdx]);
3232         }
3233     }
3234 
3235     m_occlusionObjectsOffset = mainObjectsVerticesCount;
3236 }
3237 
3238 // Extract single values or pairs of consecutive values from src and store them in dst1 and dst2.
3239 // If ds2 is not null, src is processed as containing pairs of values.
3240 // The first value will be stored in ds1 and the second one in dst2.
unpackValues(const std::vector<uint64_t> & src,std::vector<uint64_t> * dst1,std::vector<uint64_t> * dst2)3241 void unpackValues(const std::vector<uint64_t> &src, std::vector<uint64_t> *dst1, std::vector<uint64_t> *dst2)
3242 {
3243     if (!dst2)
3244     {
3245         std::copy(begin(src), end(src), begin(*dst1));
3246         return;
3247     }
3248 
3249     constexpr size_t sz0 = 0;
3250     constexpr size_t sz1 = 1;
3251     constexpr size_t sz2 = 2;
3252 
3253     DE_UNREF(sz0); // For release builds.
3254     DE_ASSERT(src.size() % sz2 == sz0);
3255 
3256     for (size_t i = 0; i < src.size(); i += sz2)
3257     {
3258         const auto j = i / sz2;
3259         dst1->at(j)  = src.at(i);
3260         dst2->at(j)  = src.at(i + sz1);
3261     }
3262 }
3263 
draw(const uint32_t subpassCount,VkRenderPass renderPass,VkFramebuffer frameBuffer,vector<PipelineSp> & pipelines)3264 void MultiViewQueriesTestInstance::draw(const uint32_t subpassCount, VkRenderPass renderPass, VkFramebuffer frameBuffer,
3265                                         vector<PipelineSp> &pipelines)
3266 {
3267     const VkRect2D renderArea                = {{0, 0}, {m_parameters.extent.width, m_parameters.extent.height}};
3268     const VkClearValue renderPassClearValue  = makeClearValueColor(tcu::Vec4(0.0f));
3269     const VkBuffer vertexBuffers[]           = {*m_vertexCoordBuffer, *m_vertexColorBuffer};
3270     const VkDeviceSize vertexBufferOffsets[] = {0u, 0u};
3271     const uint32_t drawCountPerSubpass       = (subpassCount == 1) ? m_squareCount : 1u;
3272     const uint32_t queryCountersNumber =
3273         (subpassCount == 1) ? m_squareCount * getUsedViewsCount(0) : getQueryCountersNumber();
3274 
3275     const VkQueryPoolCreateInfo occlusionQueryPoolCreateInfo = {
3276         VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, //  VkStructureType sType;
3277         DE_NULL,                                  //  const void* pNext;
3278         (VkQueryPoolCreateFlags)0,                //  VkQueryPoolCreateFlags flags;
3279         VK_QUERY_TYPE_OCCLUSION,                  //  VkQueryType queryType;
3280         queryCountersNumber,                      //  uint32_t queryCount;
3281         0u,                                       //  VkQueryPipelineStatisticFlags pipelineStatistics;
3282     };
3283     const VkQueryPoolCreateInfo timestampQueryPoolCreateInfo = {
3284         VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, //  VkStructureType sType;
3285         DE_NULL,                                  //  const void* pNext;
3286         (VkQueryPoolCreateFlags)0,                //  VkQueryPoolCreateFlags flags;
3287         VK_QUERY_TYPE_TIMESTAMP,                  //  VkQueryType queryType;
3288         queryCountersNumber,                      //  uint32_t queryCount;
3289         0u,                                       //  VkQueryPipelineStatisticFlags pipelineStatistics;
3290     };
3291     const Unique<VkQueryPool> occlusionQueryPool(
3292         createQueryPool(*m_device, *m_logicalDevice, &occlusionQueryPoolCreateInfo));
3293     const Unique<VkQueryPool> timestampStartQueryPool(
3294         createQueryPool(*m_device, *m_logicalDevice, &timestampQueryPoolCreateInfo));
3295     const Unique<VkQueryPool> timestampEndQueryPool(
3296         createQueryPool(*m_device, *m_logicalDevice, &timestampQueryPoolCreateInfo));
3297     uint32_t queryStartIndex = 0;
3298 
3299     const bool withAvailability   = (m_parameters.viewIndex == TEST_TYPE_NON_PRECISE_QUERIES_WITH_AVAILABILITY);
3300     const uint32_t valuesPerQuery = (withAvailability ? 2u : 1u);
3301     const uint32_t valuesNumber   = queryCountersNumber * valuesPerQuery;
3302     const auto queryStride        = static_cast<VkDeviceSize>(sizeof(uint64_t) * valuesPerQuery);
3303     const auto extraFlag =
3304         (withAvailability ? VK_QUERY_RESULT_WITH_AVAILABILITY_BIT : static_cast<VkQueryResultFlagBits>(0));
3305     const auto queryFlags = (VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT | extraFlag);
3306 
3307     vk::BufferWithMemory queryBuffer(
3308         m_context.getDeviceInterface(), *m_logicalDevice, *m_allocator,
3309         makeBufferCreateInfo(valuesNumber * sizeof(uint64_t),
3310                              VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT),
3311         vk::MemoryRequirement::HostVisible);
3312 
3313     beginCommandBuffer(*m_device, *m_cmdBuffer);
3314 
3315     beforeRenderPass();
3316 
3317     // Query pools must be reset before use
3318     m_device->cmdResetQueryPool(*m_cmdBuffer, *occlusionQueryPool, queryStartIndex, queryCountersNumber);
3319     m_device->cmdResetQueryPool(*m_cmdBuffer, *timestampStartQueryPool, queryStartIndex, queryCountersNumber);
3320     m_device->cmdResetQueryPool(*m_cmdBuffer, *timestampEndQueryPool, queryStartIndex, queryCountersNumber);
3321 
3322     if (!m_useDynamicRendering)
3323     {
3324         const VkRenderPassBeginInfo renderPassBeginInfo{
3325             VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, //  VkStructureType sType;
3326             DE_NULL,                                  //  const void* pNext;
3327             renderPass,                               //  VkRenderPass renderPass;
3328             frameBuffer,                              //  VkFramebuffer framebuffer;
3329             renderArea,                               //  VkRect2D renderArea;
3330             1u,                                       //  uint32_t clearValueCount;
3331             &renderPassClearValue,                    //  const VkClearValue* pClearValues;
3332         };
3333         cmdBeginRenderPass(*m_device, *m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE,
3334                            m_parameters.renderingType);
3335     }
3336 
3337     m_occlusionExpectedValues.reserve(queryCountersNumber);
3338     m_counterSeriesStart.reserve(queryCountersNumber);
3339     m_counterSeriesEnd.reserve(queryCountersNumber);
3340 
3341     for (uint32_t subpassNdx = 0u; subpassNdx < subpassCount; subpassNdx++)
3342     {
3343         uint32_t queryCountersToUse = getUsedViewsCount(subpassNdx);
3344 
3345         m_device->cmdBindVertexBuffers(*m_cmdBuffer, 0u, DE_LENGTH_OF_ARRAY(vertexBuffers), vertexBuffers,
3346                                        vertexBufferOffsets);
3347         m_device->cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipelines[subpassNdx]);
3348 
3349 #ifndef CTS_USES_VULKANSC
3350         if (m_useDynamicRendering)
3351         {
3352             addRenderingSubpassDependencyIfRequired(subpassNdx);
3353 
3354             beginRendering(*m_device, *m_cmdBuffer, m_colorAttachment->getImageView(), renderArea, renderPassClearValue,
3355                            VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
3356                            (subpassNdx ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_CLEAR), 0u,
3357                            m_parameters.extent.depth, m_parameters.viewMasks[subpassNdx]);
3358         }
3359 #endif // CTS_USES_VULKANSC
3360 
3361         for (uint32_t drawNdx = 0u; drawNdx < drawCountPerSubpass; ++drawNdx)
3362         {
3363             const uint32_t primitiveNumber = drawNdx + subpassNdx % m_squareCount;
3364             const uint32_t firstVertex     = primitiveNumber * m_verticesPerPrimitive;
3365 
3366             m_device->cmdWriteTimestamp(*m_cmdBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, *timestampStartQueryPool,
3367                                         queryStartIndex);
3368             {
3369                 m_device->cmdDraw(*m_cmdBuffer, m_verticesPerPrimitive, 1u, firstVertex, 0u);
3370 
3371                 // Render occluded object
3372                 m_device->cmdBeginQuery(*m_cmdBuffer, *occlusionQueryPool, queryStartIndex, m_occlusionQueryFlags);
3373                 m_device->cmdDraw(*m_cmdBuffer, m_verticesPerPrimitive, 1u, m_occlusionObjectsOffset + firstVertex, 0u);
3374                 m_device->cmdEndQuery(*m_cmdBuffer, *occlusionQueryPool, queryStartIndex);
3375 
3376                 for (uint32_t viewMaskNdx = 0; viewMaskNdx < queryCountersToUse; ++viewMaskNdx)
3377                 {
3378                     m_occlusionExpectedValues.push_back(m_occlusionObjectPixelsCount[primitiveNumber]);
3379                     m_counterSeriesStart.push_back(viewMaskNdx == 0);
3380                     m_counterSeriesEnd.push_back(viewMaskNdx + 1 == queryCountersToUse);
3381                 }
3382             }
3383             m_device->cmdWriteTimestamp(*m_cmdBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, *timestampEndQueryPool,
3384                                         queryStartIndex);
3385 
3386             queryStartIndex += queryCountersToUse;
3387         }
3388 
3389 #ifndef CTS_USES_VULKANSC
3390         if (m_useDynamicRendering)
3391             endRendering(*m_device, *m_cmdBuffer);
3392         else
3393 #endif // CTS_USES_VULKANSC
3394             if (subpassNdx < subpassCount - 1u)
3395                 cmdNextSubpass(*m_device, *m_cmdBuffer, VK_SUBPASS_CONTENTS_INLINE, m_parameters.renderingType);
3396     }
3397 
3398     DE_ASSERT(queryStartIndex == queryCountersNumber);
3399 
3400     if (!m_useDynamicRendering)
3401         cmdEndRenderPass(*m_device, *m_cmdBuffer, m_parameters.renderingType);
3402 
3403     afterRenderPass();
3404 
3405     if (m_cmdCopyQueryPoolResults)
3406         m_device->cmdCopyQueryPoolResults(*m_cmdBuffer, *occlusionQueryPool, 0u, queryCountersNumber, *queryBuffer, 0u,
3407                                           queryStride, queryFlags);
3408 
3409     VK_CHECK(m_device->endCommandBuffer(*m_cmdBuffer));
3410     submitCommandsAndWait(*m_device, *m_logicalDevice, m_queue, *m_cmdBuffer);
3411 
3412     // These vectors will temporarily hold results.
3413     std::vector<uint64_t> occlusionQueryResultsBuffer(valuesNumber, 0u);
3414     std::vector<uint64_t> timestampStartQueryResultsBuffer(valuesNumber, 0u);
3415     std::vector<uint64_t> timestampEndQueryResultsBuffer(valuesNumber, 0u);
3416 
3417     m_occlusionValues.resize(queryCountersNumber);
3418     m_timestampStartValues.resize(queryCountersNumber);
3419     m_timestampEndValues.resize(queryCountersNumber);
3420 
3421     if (withAvailability)
3422     {
3423         m_occlusionAvailabilityValues.resize(queryCountersNumber);
3424         m_timestampStartAvailabilityValues.resize(queryCountersNumber);
3425         m_timestampEndAvailabilityValues.resize(queryCountersNumber);
3426     }
3427 
3428     if (m_cmdCopyQueryPoolResults)
3429     {
3430         memcpy(occlusionQueryResultsBuffer.data(), queryBuffer.getAllocation().getHostPtr(),
3431                de::dataSize(occlusionQueryResultsBuffer));
3432         memcpy(timestampStartQueryResultsBuffer.data(), queryBuffer.getAllocation().getHostPtr(),
3433                de::dataSize(timestampStartQueryResultsBuffer));
3434         memcpy(timestampEndQueryResultsBuffer.data(), queryBuffer.getAllocation().getHostPtr(),
3435                de::dataSize(timestampEndQueryResultsBuffer));
3436     }
3437     else
3438     {
3439         m_device->getQueryPoolResults(*m_logicalDevice, *occlusionQueryPool, 0u, queryCountersNumber,
3440                                       de::dataSize(occlusionQueryResultsBuffer),
3441                                       de::dataOrNull(occlusionQueryResultsBuffer), queryStride, queryFlags);
3442         m_device->getQueryPoolResults(*m_logicalDevice, *timestampStartQueryPool, 0u, queryCountersNumber,
3443                                       de::dataSize(timestampStartQueryResultsBuffer),
3444                                       de::dataOrNull(timestampStartQueryResultsBuffer), queryStride, queryFlags);
3445         m_device->getQueryPoolResults(*m_logicalDevice, *timestampEndQueryPool, 0u, queryCountersNumber,
3446                                       de::dataSize(timestampEndQueryResultsBuffer),
3447                                       de::dataOrNull(timestampEndQueryResultsBuffer), queryStride, queryFlags);
3448     }
3449 
3450     unpackValues(occlusionQueryResultsBuffer, &m_occlusionValues,
3451                  (withAvailability ? &m_occlusionAvailabilityValues : nullptr));
3452     unpackValues(timestampStartQueryResultsBuffer, &m_timestampStartValues,
3453                  (withAvailability ? &m_timestampStartAvailabilityValues : nullptr));
3454     unpackValues(timestampEndQueryResultsBuffer, &m_timestampEndValues,
3455                  (withAvailability ? &m_timestampEndAvailabilityValues : nullptr));
3456 
3457     for (uint32_t ndx = 0; ndx < m_timestampStartValues.size(); ++ndx)
3458         m_timestampStartValues[ndx] &= m_timestampMask;
3459 
3460     for (uint32_t ndx = 0; ndx < m_timestampEndValues.size(); ++ndx)
3461         m_timestampEndValues[ndx] &= m_timestampMask;
3462 }
3463 
getUsedViewsCount(const uint32_t viewMaskIndex)3464 uint32_t MultiViewQueriesTestInstance::getUsedViewsCount(const uint32_t viewMaskIndex)
3465 {
3466     uint32_t result = 0;
3467 
3468     for (uint32_t viewMask = m_parameters.viewMasks[viewMaskIndex]; viewMask != 0; viewMask >>= 1)
3469         if ((viewMask & 1) != 0)
3470             result++;
3471 
3472     return result;
3473 }
3474 
getQueryCountersNumber()3475 uint32_t MultiViewQueriesTestInstance::getQueryCountersNumber()
3476 {
3477     uint32_t result = 0;
3478 
3479     for (uint32_t i = 0; i < m_parameters.viewMasks.size(); ++i)
3480         result += getUsedViewsCount(i);
3481 
3482     return result;
3483 }
3484 
3485 class MultiViewReadbackTestInstance : public MultiViewRenderTestInstance
3486 {
3487 public:
3488     MultiViewReadbackTestInstance(Context &context, const TestParameters &parameters);
3489 
3490 protected:
3491     tcu::TestStatus iterate(void);
3492     void drawClears(const uint32_t subpassCount, VkRenderPass renderPass, VkFramebuffer frameBuffer,
3493                     vector<PipelineSp> &pipelines, const bool clearPass);
3494     void clear(const VkCommandBuffer commandBuffer, const VkRect2D &clearRect2D, const tcu::Vec4 &clearColor);
3495 
3496 private:
3497     vector<VkRect2D> m_quarters;
3498 };
3499 
MultiViewReadbackTestInstance(Context & context,const TestParameters & parameters)3500 MultiViewReadbackTestInstance::MultiViewReadbackTestInstance(Context &context, const TestParameters &parameters)
3501     : MultiViewRenderTestInstance(context, parameters)
3502 {
3503     const uint32_t halfWidth  = m_parameters.extent.width / 2;
3504     const uint32_t halfHeight = m_parameters.extent.height / 2;
3505 
3506     for (int32_t x = 0; x < 2; ++x)
3507         for (int32_t y = 0; y < 2; ++y)
3508         {
3509             const int32_t offsetX = static_cast<int32_t>(halfWidth) * x;
3510             const int32_t offsetY = static_cast<int32_t>(halfHeight) * y;
3511             const VkRect2D area   = {{offsetX, offsetY}, {halfWidth, halfHeight}};
3512 
3513             m_quarters.push_back(area);
3514         }
3515 }
3516 
iterate(void)3517 tcu::TestStatus MultiViewReadbackTestInstance::iterate(void)
3518 {
3519     const uint32_t subpassCount = static_cast<uint32_t>(m_parameters.viewMasks.size());
3520 
3521     createCommandBuffer();
3522 
3523     for (uint32_t pass = 0; pass < 2; ++pass)
3524     {
3525         const bool fullClearPass = (pass == 0);
3526         const VkAttachmentLoadOp loadOp =
3527             (!fullClearPass)                                                   ? VK_ATTACHMENT_LOAD_OP_LOAD :
3528             (m_parameters.viewIndex == TEST_TYPE_READBACK_WITH_IMPLICIT_CLEAR) ? VK_ATTACHMENT_LOAD_OP_CLEAR :
3529             (m_parameters.viewIndex == TEST_TYPE_READBACK_WITH_EXPLICIT_CLEAR) ? VK_ATTACHMENT_LOAD_OP_DONT_CARE :
3530                                                                                  VK_ATTACHMENT_LOAD_OP_DONT_CARE;
3531         Move<VkRenderPass> renderPass;
3532         Move<VkFramebuffer> frameBuffer;
3533         Unique<VkPipelineLayout> pipelineLayout(makePipelineLayout(*m_device, *m_logicalDevice));
3534         vector<PipelineSp> pipelines(subpassCount);
3535         map<VkShaderStageFlagBits, ShaderModuleSP> shaderModule;
3536 
3537         if (m_parameters.renderingType != RENDERING_TYPE_DYNAMIC_RENDERING)
3538         {
3539             renderPass  = makeRenderPass(*m_device, *m_logicalDevice, m_parameters.colorFormat, m_parameters.viewMasks,
3540                                          m_parameters.renderingType, VK_SAMPLE_COUNT_1_BIT, loadOp);
3541             frameBuffer = makeFramebuffer(*m_device, *m_logicalDevice, *renderPass, m_colorAttachment->getImageView(),
3542                                           m_parameters.extent.width, m_parameters.extent.height);
3543         }
3544 
3545         {
3546             vector<VkPipelineShaderStageCreateInfo> shaderStageParams;
3547             madeShaderModule(shaderModule, shaderStageParams);
3548             for (uint32_t subpassNdx = 0u; subpassNdx < subpassCount; ++subpassNdx)
3549                 pipelines[subpassNdx] = (PipelineSp(new Unique<VkPipeline>(
3550                     makeGraphicsPipeline(*renderPass, *pipelineLayout, static_cast<uint32_t>(shaderStageParams.size()),
3551                                          shaderStageParams.data(), subpassNdx))));
3552         }
3553 
3554         drawClears(subpassCount, *renderPass, *frameBuffer, pipelines, fullClearPass);
3555     }
3556 
3557     {
3558         vector<uint8_t> pixelAccessData(m_parameters.extent.width * m_parameters.extent.height *
3559                                         m_parameters.extent.depth *
3560                                         mapVkFormat(m_parameters.colorFormat).getPixelSize());
3561         tcu::PixelBufferAccess dst(mapVkFormat(m_parameters.colorFormat), m_parameters.extent.width,
3562                                    m_parameters.extent.height, m_parameters.extent.depth, pixelAccessData.data());
3563 
3564         readImage(m_colorAttachment->getImage(), dst);
3565 
3566         if (!checkImage(dst))
3567             return tcu::TestStatus::fail("Fail");
3568     }
3569 
3570     return tcu::TestStatus::pass("Pass");
3571 }
3572 
drawClears(const uint32_t subpassCount,VkRenderPass renderPass,VkFramebuffer frameBuffer,vector<PipelineSp> & pipelines,const bool clearPass)3573 void MultiViewReadbackTestInstance::drawClears(const uint32_t subpassCount, VkRenderPass renderPass,
3574                                                VkFramebuffer frameBuffer, vector<PipelineSp> &pipelines,
3575                                                const bool clearPass)
3576 {
3577     const VkRect2D renderArea               = {{0, 0}, {m_parameters.extent.width, m_parameters.extent.height}};
3578     const VkClearValue renderPassClearValue = makeClearValueColor(m_colorTable[0]);
3579     const uint32_t drawCountPerSubpass      = (subpassCount == 1) ? m_squareCount : 1u;
3580     const bool withClearColor = (clearPass && m_parameters.viewIndex == TEST_TYPE_READBACK_WITH_IMPLICIT_CLEAR);
3581 
3582     beginCommandBuffer(*m_device, *m_cmdBuffer);
3583 
3584     if (clearPass)
3585         beforeRenderPass();
3586 
3587     if (!m_useDynamicRendering)
3588     {
3589         const VkRenderPassBeginInfo renderPassBeginInfo{
3590             VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,         //  VkStructureType sType;
3591             DE_NULL,                                          //  const void* pNext;
3592             renderPass,                                       //  VkRenderPass renderPass;
3593             frameBuffer,                                      //  VkFramebuffer framebuffer;
3594             renderArea,                                       //  VkRect2D renderArea;
3595             withClearColor ? 1u : 0u,                         //  uint32_t clearValueCount;
3596             withClearColor ? &renderPassClearValue : DE_NULL, //  const VkClearValue* pClearValues;
3597         };
3598         cmdBeginRenderPass(*m_device, *m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE,
3599                            m_parameters.renderingType);
3600     }
3601 
3602     for (uint32_t subpassNdx = 0u; subpassNdx < subpassCount; subpassNdx++)
3603     {
3604         m_device->cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipelines[subpassNdx]);
3605 
3606 #ifndef CTS_USES_VULKANSC
3607         if (m_useDynamicRendering)
3608         {
3609             addRenderingSubpassDependencyIfRequired(subpassNdx);
3610 
3611             VkAttachmentLoadOp loadOperation = VK_ATTACHMENT_LOAD_OP_LOAD;
3612             if (clearPass)
3613             {
3614                 if (m_parameters.viewIndex == TEST_TYPE_READBACK_WITH_IMPLICIT_CLEAR)
3615                     loadOperation = VK_ATTACHMENT_LOAD_OP_CLEAR;
3616                 else if (m_parameters.viewIndex == TEST_TYPE_READBACK_WITH_EXPLICIT_CLEAR)
3617                     loadOperation = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
3618                 else
3619                     loadOperation = VK_ATTACHMENT_LOAD_OP_MAX_ENUM;
3620             }
3621 
3622             beginRendering(*m_device, *m_cmdBuffer, m_colorAttachment->getImageView(), renderArea, renderPassClearValue,
3623                            VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, loadOperation, 0u, m_parameters.extent.depth,
3624                            m_parameters.viewMasks[subpassNdx]);
3625         }
3626 #endif // CTS_USES_VULKANSC
3627 
3628         if (clearPass)
3629         {
3630             if (m_parameters.viewIndex == TEST_TYPE_READBACK_WITH_EXPLICIT_CLEAR)
3631                 clear(*m_cmdBuffer, renderArea, m_colorTable[subpassNdx % 4]);
3632         }
3633         else
3634         {
3635             for (uint32_t drawNdx = 0u; drawNdx < drawCountPerSubpass; ++drawNdx)
3636             {
3637                 const uint32_t primitiveNumber = drawNdx + subpassNdx % m_squareCount;
3638 
3639                 clear(*m_cmdBuffer, m_quarters[primitiveNumber], m_colorTable[4 + primitiveNumber]);
3640             }
3641         }
3642 
3643 #ifndef CTS_USES_VULKANSC
3644         if (m_useDynamicRendering)
3645             endRendering(*m_device, *m_cmdBuffer);
3646         else
3647 #endif // CTS_USES_VULKANSC
3648             if (subpassNdx < subpassCount - 1u)
3649                 cmdNextSubpass(*m_device, *m_cmdBuffer, VK_SUBPASS_CONTENTS_INLINE, m_parameters.renderingType);
3650     }
3651 
3652     if (!m_useDynamicRendering)
3653         cmdEndRenderPass(*m_device, *m_cmdBuffer, m_parameters.renderingType);
3654 
3655     if (!clearPass)
3656         afterRenderPass();
3657 
3658     VK_CHECK(m_device->endCommandBuffer(*m_cmdBuffer));
3659     submitCommandsAndWait(*m_device, *m_logicalDevice, m_queue, *m_cmdBuffer);
3660 }
3661 
clear(const VkCommandBuffer commandBuffer,const VkRect2D & clearRect2D,const tcu::Vec4 & clearColor)3662 void MultiViewReadbackTestInstance::clear(const VkCommandBuffer commandBuffer, const VkRect2D &clearRect2D,
3663                                           const tcu::Vec4 &clearColor)
3664 {
3665     const VkClearRect clearRect = {
3666         clearRect2D, //  VkRect2D    rect
3667         0u,          //  uint32_t    baseArrayLayer
3668         1u,          //  uint32_t    layerCount
3669     };
3670     const VkClearAttachment clearAttachment = {
3671         VK_IMAGE_ASPECT_COLOR_BIT,      //  VkImageAspectFlags    aspectMask
3672         0u,                             //  uint32_t            colorAttachment
3673         makeClearValueColor(clearColor) //  VkClearValue        clearValue
3674     };
3675 
3676     m_device->cmdClearAttachments(commandBuffer, 1u, &clearAttachment, 1u, &clearRect);
3677 }
3678 
3679 class MultiViewDepthStencilTestInstance : public MultiViewRenderTestInstance
3680 {
3681 public:
3682     MultiViewDepthStencilTestInstance(Context &context, const TestParameters &parameters);
3683 
3684 protected:
3685     tcu::TestStatus iterate(void) override;
3686     void createVertexData(void) override;
3687 
3688     void draw(const uint32_t subpassCount, VkRenderPass renderPass, VkFramebuffer frameBuffer,
3689               vector<PipelineSp> &pipelines) override;
3690     void beforeRenderPass(void) override;
3691     void afterRenderPass(void) override;
3692     vector<VkImageView> makeAttachmentsVector(void);
3693     MovePtr<tcu::Texture2DArray> imageData(void) const override;
3694     void readImage(VkImage image, const tcu::PixelBufferAccess &dst);
3695     vector<tcu::Vec2> getDepthRanges(void) const;
3696 
3697 private:
3698     VkFormat m_dsFormat;
3699     de::SharedPtr<ImageAttachment> m_dsAttachment;
3700     bool m_depthTest;
3701     bool m_stencilTest;
3702 };
3703 
MultiViewDepthStencilTestInstance(Context & context,const TestParameters & parameters)3704 MultiViewDepthStencilTestInstance::MultiViewDepthStencilTestInstance(Context &context, const TestParameters &parameters)
3705     : MultiViewRenderTestInstance(context, parameters)
3706     , m_dsFormat(VK_FORMAT_UNDEFINED)
3707     , m_depthTest(m_parameters.viewIndex == TEST_TYPE_DEPTH ||
3708                   m_parameters.viewIndex == TEST_TYPE_DEPTH_DIFFERENT_RANGES)
3709     , m_stencilTest(m_parameters.viewIndex == TEST_TYPE_STENCIL)
3710 {
3711     const VkFormat formats[] = {VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_D32_SFLOAT_S8_UINT};
3712 
3713     for (uint32_t ndx = 0; ndx < DE_LENGTH_OF_ARRAY(formats); ++ndx)
3714     {
3715         const VkFormat format                     = formats[ndx];
3716         const auto &vki                           = m_context.getInstanceInterface();
3717         const auto physicalDevice                 = m_context.getPhysicalDevice();
3718         const VkFormatProperties formatProperties = getPhysicalDeviceFormatProperties(vki, physicalDevice, format);
3719 
3720         if ((formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0)
3721         {
3722             m_dsFormat = format;
3723 
3724             break;
3725         }
3726     }
3727 
3728     if (m_dsFormat == VK_FORMAT_UNDEFINED)
3729         TCU_FAIL("Supported depth/stencil format not found, that violates specification");
3730 
3731     // Depth/stencil attachment
3732     m_dsAttachment = de::SharedPtr<ImageAttachment>(
3733         new ImageAttachment(*m_logicalDevice, *m_device, *m_allocator, m_parameters.extent, m_dsFormat));
3734 }
3735 
makeAttachmentsVector(void)3736 vector<VkImageView> MultiViewDepthStencilTestInstance::makeAttachmentsVector(void)
3737 {
3738     vector<VkImageView> attachments;
3739 
3740     attachments.push_back(m_colorAttachment->getImageView());
3741     attachments.push_back(m_dsAttachment->getImageView());
3742 
3743     return attachments;
3744 }
3745 
imageData(void) const3746 MovePtr<tcu::Texture2DArray> MultiViewDepthStencilTestInstance::imageData(void) const
3747 {
3748     MovePtr<tcu::Texture2DArray> referenceFrame = MovePtr<tcu::Texture2DArray>(
3749         new tcu::Texture2DArray(mapVkFormat(m_parameters.colorFormat), m_parameters.extent.width,
3750                                 m_parameters.extent.height, m_parameters.extent.depth));
3751     const uint32_t subpassCount         = static_cast<uint32_t>(m_parameters.viewMasks.size());
3752     const vector<tcu::Vec2> depthRanges = getDepthRanges();
3753 
3754     referenceFrame->allocLevel(0);
3755     deMemset(referenceFrame->getLevel(0).getDataPtr(), 0,
3756              m_parameters.extent.width * m_parameters.extent.height * m_parameters.extent.depth *
3757                  mapVkFormat(m_parameters.colorFormat).getPixelSize());
3758 
3759     for (uint32_t layerNdx = 0; layerNdx < m_parameters.extent.depth; ++layerNdx)
3760         fillLayer(referenceFrame->getLevel(0), getQuarterRefColor(0u, 0u, 0u, false), layerNdx);
3761 
3762     for (uint32_t subpassNdx = 0u; subpassNdx < subpassCount; subpassNdx++)
3763     {
3764         int layerNdx                = 0;
3765         uint32_t mask               = m_parameters.viewMasks[subpassNdx];
3766         const tcu::Vec2 &depthRange = depthRanges[subpassNdx];
3767         const float depthMin        = depthRange[0];
3768         const float depthMax        = depthRange[1];
3769 
3770         // iterate over image layers
3771         while (mask > 0u)
3772         {
3773             if (mask & 1u)
3774             {
3775                 const uint32_t subpassQuarterNdx = subpassNdx % m_squareCount;
3776                 const int colorNdx               = subpassQuarterNdx * 4;
3777                 tcu::Vec4 color = getQuarterRefColor(subpassQuarterNdx, colorNdx, layerNdx, true, subpassNdx);
3778 
3779                 if (m_parameters.viewIndex == TEST_TYPE_DEPTH_DIFFERENT_RANGES)
3780                 {
3781                     // quads with depth out of range should be cliiped
3782                     // to simplify code we are drawing them with background color
3783                     if ((color.x() < 0.0f) || (color.x() > 1.0f))
3784                         color.x() = 1.0f;
3785                     else
3786                     {
3787                         const float depthClamped = de::clamp(color.x(), 0.0f, 1.0f);
3788                         color.x()                = depthClamped * depthMax + (1.0f - depthClamped) * depthMin;
3789                     }
3790                 }
3791 
3792                 fillQuarter(referenceFrame->getLevel(0), color, layerNdx, subpassQuarterNdx, subpassNdx);
3793             }
3794 
3795             mask = mask >> 1;
3796             ++layerNdx;
3797         }
3798     }
3799     return referenceFrame;
3800 }
3801 
readImage(VkImage image,const tcu::PixelBufferAccess & dst)3802 void MultiViewDepthStencilTestInstance::readImage(VkImage image, const tcu::PixelBufferAccess &dst)
3803 {
3804     const VkFormat bufferFormat              = m_depthTest   ? getDepthBufferFormat(m_dsFormat) :
3805                                                m_stencilTest ? getStencilBufferFormat(m_dsFormat) :
3806                                                                VK_FORMAT_UNDEFINED;
3807     const uint32_t imagePixelSize            = static_cast<uint32_t>(tcu::getPixelSize(mapVkFormat(bufferFormat)));
3808     const VkDeviceSize pixelDataSize         = dst.getWidth() * dst.getHeight() * dst.getDepth() * imagePixelSize;
3809     const tcu::TextureFormat tcuBufferFormat = mapVkFormat(bufferFormat);
3810     Move<VkBuffer> buffer;
3811     MovePtr<Allocation> bufferAlloc;
3812 
3813     // Create destination buffer
3814     {
3815         const VkBufferCreateInfo bufferParams = {
3816             VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
3817             DE_NULL,                              // const void* pNext;
3818             0u,                                   // VkBufferCreateFlags flags;
3819             pixelDataSize,                        // VkDeviceSize size;
3820             VK_BUFFER_USAGE_TRANSFER_DST_BIT,     // VkBufferUsageFlags usage;
3821             VK_SHARING_MODE_EXCLUSIVE,            // VkSharingMode sharingMode;
3822             1u,                                   // uint32_t queueFamilyIndexCount;
3823             &m_queueFamilyIndex,                  // const uint32_t* pQueueFamilyIndices;
3824         };
3825 
3826         buffer      = createBuffer(*m_device, *m_logicalDevice, &bufferParams);
3827         bufferAlloc = m_allocator->allocate(getBufferMemoryRequirements(*m_device, *m_logicalDevice, *buffer),
3828                                             MemoryRequirement::HostVisible);
3829         VK_CHECK(
3830             m_device->bindBufferMemory(*m_logicalDevice, *buffer, bufferAlloc->getMemory(), bufferAlloc->getOffset()));
3831 
3832         deMemset(bufferAlloc->getHostPtr(), 0xCC, static_cast<size_t>(pixelDataSize));
3833         flushAlloc(*m_device, *m_logicalDevice, *bufferAlloc);
3834     }
3835 
3836     const VkBufferMemoryBarrier bufferBarrier = {
3837         VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
3838         DE_NULL,                                 // const void* pNext;
3839         VK_ACCESS_TRANSFER_WRITE_BIT,            // VkAccessFlags srcAccessMask;
3840         VK_ACCESS_HOST_READ_BIT,                 // VkAccessFlags dstAccessMask;
3841         VK_QUEUE_FAMILY_IGNORED,                 // uint32_t srcQueueFamilyIndex;
3842         VK_QUEUE_FAMILY_IGNORED,                 // uint32_t dstQueueFamilyIndex;
3843         *buffer,                                 // VkBuffer buffer;
3844         0u,                                      // VkDeviceSize offset;
3845         pixelDataSize                            // VkDeviceSize size;
3846     };
3847 
3848     // Copy image to buffer
3849     const VkImageAspectFlags aspect    = m_depthTest   ? static_cast<VkImageAspectFlags>(VK_IMAGE_ASPECT_DEPTH_BIT) :
3850                                          m_stencilTest ? static_cast<VkImageAspectFlags>(VK_IMAGE_ASPECT_STENCIL_BIT) :
3851                                                          static_cast<VkImageAspectFlags>(0u);
3852     const VkBufferImageCopy copyRegion = {0u,                        // VkDeviceSize bufferOffset;
3853                                           (uint32_t)dst.getWidth(),  // uint32_t bufferRowLength;
3854                                           (uint32_t)dst.getHeight(), // uint32_t bufferImageHeight;
3855                                           {
3856                                               aspect,                    // VkImageAspectFlags aspect;
3857                                               0u,                        // uint32_t mipLevel;
3858                                               0u,                        // uint32_t baseArrayLayer;
3859                                               m_parameters.extent.depth, // uint32_t layerCount;
3860                                           },                             // VkImageSubresourceLayers imageSubresource;
3861                                           {0, 0, 0},                     // VkOffset3D imageOffset;
3862                                           {                              // VkExtent3D imageExtent;
3863                                            m_parameters.extent.width, m_parameters.extent.height, 1u}};
3864 
3865     beginCommandBuffer(*m_device, *m_cmdBuffer);
3866     {
3867         m_device->cmdCopyImageToBuffer(*m_cmdBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *buffer, 1u,
3868                                        &copyRegion);
3869         m_device->cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
3870                                      (VkDependencyFlags)0, 0, (const VkMemoryBarrier *)DE_NULL, 1, &bufferBarrier, 0u,
3871                                      DE_NULL);
3872     }
3873     VK_CHECK(m_device->endCommandBuffer(*m_cmdBuffer));
3874     submitCommandsAndWait(*m_device, *m_logicalDevice, m_queue, *m_cmdBuffer);
3875 
3876     // Read buffer data
3877     invalidateAlloc(*m_device, *m_logicalDevice, *bufferAlloc);
3878 
3879     if (m_depthTest)
3880     {
3881         // Translate depth into color space
3882         tcu::ConstPixelBufferAccess pixelBuffer(tcuBufferFormat, dst.getSize(), bufferAlloc->getHostPtr());
3883 
3884         for (int z = 0; z < pixelBuffer.getDepth(); z++)
3885             for (int y = 0; y < pixelBuffer.getHeight(); y++)
3886                 for (int x = 0; x < pixelBuffer.getWidth(); x++)
3887                 {
3888                     const float depth     = pixelBuffer.getPixDepth(x, y, z);
3889                     const tcu::Vec4 color = tcu::Vec4(depth, 0.0f, 0.0f, 1.0f);
3890 
3891                     dst.setPixel(color, x, y, z);
3892                 }
3893     }
3894 
3895     if (m_stencilTest)
3896     {
3897         // Translate stencil into color space
3898         tcu::ConstPixelBufferAccess pixelBuffer(tcuBufferFormat, dst.getSize(), bufferAlloc->getHostPtr());
3899         const tcu::Vec4 baseColor   = getQuarterRefColor(0u, 0u, 0u, false);
3900         const tcu::Vec4 colorStep   = getQuarterRefColor(0u, 0u, 0u, true);
3901         const tcu::Vec4 colorMap[4] = {
3902             baseColor,
3903             tcu::Vec4(1.0f * colorStep[0], 0.0f, 0.0f, 1.0),
3904             tcu::Vec4(2.0f * colorStep[0], 0.0f, 0.0f, 1.0),
3905             tcu::Vec4(3.0f * colorStep[0], 0.0f, 0.0f, 1.0),
3906         };
3907         const tcu::Vec4 invalidColor = tcu::Vec4(0.0f);
3908 
3909         for (int z = 0; z < pixelBuffer.getDepth(); z++)
3910             for (int y = 0; y < pixelBuffer.getHeight(); y++)
3911                 for (int x = 0; x < pixelBuffer.getWidth(); x++)
3912                 {
3913                     const int stencilInt = pixelBuffer.getPixStencil(x, y, z);
3914                     const tcu::Vec4 &color =
3915                         de::inRange(stencilInt, 0, DE_LENGTH_OF_ARRAY(colorMap)) ? colorMap[stencilInt] : invalidColor;
3916 
3917                     dst.setPixel(color, x, y, z);
3918                 }
3919     }
3920 }
3921 
iterate(void)3922 tcu::TestStatus MultiViewDepthStencilTestInstance::iterate(void)
3923 {
3924     const uint32_t subpassCount = static_cast<uint32_t>(m_parameters.viewMasks.size());
3925     Move<VkRenderPass> renderPass;
3926     vector<VkImageView> attachments(makeAttachmentsVector());
3927     Move<VkFramebuffer> frameBuffer;
3928     Unique<VkPipelineLayout> pipelineLayout(makePipelineLayout(*m_device, *m_logicalDevice));
3929     vector<PipelineSp> pipelines(subpassCount);
3930     const vector<tcu::Vec2> depthRanges(getDepthRanges());
3931     map<VkShaderStageFlagBits, ShaderModuleSP> shaderModule;
3932 
3933     if (m_parameters.renderingType != RENDERING_TYPE_DYNAMIC_RENDERING)
3934     {
3935         renderPass = makeRenderPassWithDepth(*m_device, *m_logicalDevice, m_parameters.colorFormat,
3936                                              m_parameters.viewMasks, m_dsFormat, m_parameters.renderingType);
3937         frameBuffer =
3938             makeFramebuffer(*m_device, *m_logicalDevice, *renderPass, static_cast<uint32_t>(attachments.size()),
3939                             attachments.data(), m_parameters.extent.width, m_parameters.extent.height, 1u);
3940     }
3941 
3942     if (m_parameters.renderingType != RENDERING_TYPE_DYNAMIC_RENDERING)
3943     {
3944         renderPass = makeRenderPassWithDepth(*m_device, *m_logicalDevice, m_parameters.colorFormat,
3945                                              m_parameters.viewMasks, m_dsFormat, m_parameters.renderingType);
3946         frameBuffer =
3947             makeFramebuffer(*m_device, *m_logicalDevice, *renderPass, static_cast<uint32_t>(attachments.size()),
3948                             attachments.data(), m_parameters.extent.width, m_parameters.extent.height, 1u);
3949     }
3950 
3951     {
3952         vector<VkPipelineShaderStageCreateInfo> shaderStageParams;
3953         madeShaderModule(shaderModule, shaderStageParams);
3954         for (uint32_t subpassNdx = 0u; subpassNdx < subpassCount; ++subpassNdx)
3955         {
3956             const tcu::Vec2 &depthRange = depthRanges[subpassNdx];
3957             const float depthMin        = depthRange[0];
3958             const float depthMax        = depthRange[1];
3959 
3960             pipelines[subpassNdx] = (PipelineSp(new Unique<VkPipeline>(makeGraphicsPipeline(
3961                 *renderPass, *pipelineLayout, static_cast<uint32_t>(shaderStageParams.size()), shaderStageParams.data(),
3962                 subpassNdx, VK_VERTEX_INPUT_RATE_VERTEX, m_depthTest, m_stencilTest, depthMin, depthMax, m_dsFormat))));
3963         }
3964     }
3965 
3966     createCommandBuffer();
3967     createVertexData();
3968     createVertexBuffer();
3969 
3970     draw(subpassCount, *renderPass, *frameBuffer, pipelines);
3971 
3972     {
3973         vector<uint8_t> pixelAccessData(m_parameters.extent.width * m_parameters.extent.height *
3974                                         m_parameters.extent.depth *
3975                                         mapVkFormat(m_parameters.colorFormat).getPixelSize());
3976         tcu::PixelBufferAccess dst(mapVkFormat(m_parameters.colorFormat), m_parameters.extent.width,
3977                                    m_parameters.extent.height, m_parameters.extent.depth, pixelAccessData.data());
3978 
3979         readImage(m_dsAttachment->getImage(), dst);
3980 
3981         if (!checkImage(dst))
3982             return tcu::TestStatus::fail("Fail");
3983     }
3984 
3985     return tcu::TestStatus::pass("Pass");
3986 }
3987 
createVertexData(void)3988 void MultiViewDepthStencilTestInstance::createVertexData(void)
3989 {
3990     /*
3991         partA - draw vertical quads, marked with 1
3992 
3993         ViewMasks
3994         0011
3995         0110
3996         1100
3997         1001
3998 
3999         Layer3  Layer2  Layer1  Layer0
4000           ^       ^       ^       ^
4001         00|10   00|10   01|00   01|00
4002         00|10   00|10   01|00   01|00
4003         --+-->  --+-->  --+-->  --+-->
4004         00|10   01|00   01|00   00|10
4005         00|10   01|00   01|00   00|10
4006 
4007 
4008         partB - draw horizontal quads, marked with 2
4009 
4010         ViewMasks
4011         0110
4012         1100
4013         1001
4014         0011
4015 
4016         Layer3  Layer2  Layer1  Layer0
4017           ^       ^       ^       ^
4018         00|00   00|00   00|00   00|00
4019         00|22   22|00   22|00   00|22
4020         --+-->  --+-->  --+-->  --+-->
4021         22|00   22|00   00|22   00|22
4022         00|00   00|00   00|00   00|00
4023 
4024 
4025         Final - after drawing quads from partA and partB (3 marks where quads overlap)
4026 
4027         Layer3  Layer2  Layer1  Layer0
4028           ^       ^       ^       ^
4029         00|10   00|10   01|00   01|00
4030         00|32   22|10   23|00   01|22
4031         --+-->  --+-->  --+-->  --+-->
4032         22|10   23|00   01|22   00|32
4033         00|10   01|00   01|00   00|10
4034     */
4035     tcu::Vec4 color(0.0f, 0.0f, 0.0f, 1.0f); // is not essential in this test
4036     float depth(getQuarterRefColor(0u, 0u, 0u, true, 0u)[0]);
4037 
4038     // part A - four horizontal quads
4039     appendVertex(tcu::Vec4(-1.0f, -0.5f, depth, 1.0f), color); // when testing TEST_TYPE_DEPTH_DIFFERENT_RANGES
4040     appendVertex(tcu::Vec4(-1.0f, 0.0f, depth, 1.0f), color);  // this quad will have depth 1.2
4041     appendVertex(tcu::Vec4(0.0f, -0.5f, depth, 1.0f), color);  // and will be clipped in all views
4042     appendVertex(tcu::Vec4(0.0f, 0.0f, depth, 1.0f), color);
4043 
4044     depth = getQuarterRefColor(0u, 0u, 0u, true, 1u)[0];
4045     appendVertex(tcu::Vec4(-1.0f, 0.0f, depth, 1.0f), color);
4046     appendVertex(tcu::Vec4(-1.0f, 0.5f, depth, 1.0f), color);
4047     appendVertex(tcu::Vec4(0.0f, 0.0f, depth, 1.0f), color);
4048     appendVertex(tcu::Vec4(0.0f, 0.5f, depth, 1.0f), color);
4049 
4050     depth = getQuarterRefColor(0u, 0u, 0u, true, 2u)[0];
4051     appendVertex(tcu::Vec4(0.0f, -0.5f, depth, 1.0f), color);
4052     appendVertex(tcu::Vec4(0.0f, 0.0f, depth, 1.0f), color);
4053     appendVertex(tcu::Vec4(1.0f, -0.5f, depth, 1.0f), color);
4054     appendVertex(tcu::Vec4(1.0f, 0.0f, depth, 1.0f), color);
4055 
4056     depth = getQuarterRefColor(0u, 0u, 0u, true, 3u)[0];
4057     appendVertex(tcu::Vec4(0.0f, 0.0f, depth, 1.0f), color);
4058     appendVertex(tcu::Vec4(0.0f, 0.5f, depth, 1.0f), color);
4059     appendVertex(tcu::Vec4(1.0f, 0.0f, depth, 1.0f), color);
4060     appendVertex(tcu::Vec4(1.0f, 0.5f, depth, 1.0f), color);
4061 
4062     // part B - four vertical quads
4063     depth = getQuarterRefColor(0u, 0u, 0u, true, 4u)[0];
4064     appendVertex(tcu::Vec4(-0.5f, -1.0f, depth, 1.0f), color);
4065     appendVertex(tcu::Vec4(-0.5f, 0.0f, depth, 1.0f), color);
4066     appendVertex(tcu::Vec4(0.0f, -1.0f, depth, 1.0f), color);
4067     appendVertex(tcu::Vec4(0.0f, 0.0f, depth, 1.0f), color);
4068 
4069     depth = getQuarterRefColor(0u, 0u, 0u, true, 5u)[0];
4070     appendVertex(tcu::Vec4(-0.5f, 0.0f, depth, 1.0f), color);
4071     appendVertex(tcu::Vec4(-0.5f, 1.0f, depth, 1.0f), color);
4072     appendVertex(tcu::Vec4(0.0f, 0.0f, depth, 1.0f), color);
4073     appendVertex(tcu::Vec4(0.0f, 1.0f, depth, 1.0f), color);
4074 
4075     depth = getQuarterRefColor(0u, 0u, 0u, true, 6u)[0];
4076     appendVertex(tcu::Vec4(0.0f, -1.0f, depth, 1.0f), color);
4077     appendVertex(tcu::Vec4(0.0f, 0.0f, depth, 1.0f), color);
4078     appendVertex(tcu::Vec4(0.5f, -1.0f, depth, 1.0f), color);
4079     appendVertex(tcu::Vec4(0.5f, 0.0f, depth, 1.0f), color);
4080 
4081     depth = getQuarterRefColor(0u, 0u, 0u, true, 7u)[0];     // when testing TEST_TYPE_DEPTH_DIFFERENT_RANGES
4082     appendVertex(tcu::Vec4(0.0f, 0.0f, depth, 1.0f), color); // this quad will have depth -0.05
4083     appendVertex(tcu::Vec4(0.0f, 1.0f, depth, 1.0f), color); // and will be clipped in all views
4084     appendVertex(tcu::Vec4(0.5f, 0.0f, depth, 1.0f), color);
4085     appendVertex(tcu::Vec4(0.5f, 1.0f, depth, 1.0f), color);
4086 }
4087 
getDepthRanges(void) const4088 vector<tcu::Vec2> MultiViewDepthStencilTestInstance::getDepthRanges(void) const
4089 {
4090     if (TEST_TYPE_DEPTH_DIFFERENT_RANGES == m_parameters.viewIndex)
4091     {
4092         DE_ASSERT(m_parameters.viewMasks.size() == 12);
4093         return {
4094             // ranges used when four quads from part A are drawn
4095             {0.0f, 1.0f},
4096             {0.5f, 1.0f},
4097             {0.0f, 0.5f},
4098             {0.0f, 1.0f},
4099 
4100             // ranges used when four quads from part B are drawn
4101             {0.0f, 0.5f},
4102             {0.0f, 1.0f},
4103             {0.5f, 1.0f},
4104             {0.0f, 0.5f},
4105 
4106             // ranges used when part B is drawn once again
4107             {0.5f, 1.0f},
4108             {0.0f, 0.5f},
4109             {0.0f, 0.5f},
4110             {0.0f, 1.0f},
4111         };
4112     }
4113 
4114     // by defaul use <0; 1> range for all subpasses
4115     return {m_parameters.viewMasks.size(), tcu::Vec2(0.0f, 1.0f)};
4116 }
4117 
draw(const uint32_t subpassCount,VkRenderPass renderPass,VkFramebuffer frameBuffer,vector<PipelineSp> & pipelines)4118 void MultiViewDepthStencilTestInstance::draw(const uint32_t subpassCount, VkRenderPass renderPass,
4119                                              VkFramebuffer frameBuffer, vector<PipelineSp> &pipelines)
4120 {
4121     const VkRect2D renderArea                = {{0, 0}, {m_parameters.extent.width, m_parameters.extent.height}};
4122     const VkClearValue renderPassClearValue  = makeClearValueColor(tcu::Vec4(0.0f));
4123     const VkBuffer vertexBuffers[]           = {*m_vertexCoordBuffer, *m_vertexColorBuffer};
4124     const VkDeviceSize vertexBufferOffsets[] = {0u, 0u};
4125     const uint32_t drawCountPerSubpass       = (subpassCount == 1) ? m_squareCount : 1u;
4126     const uint32_t vertexPerPrimitive        = 4u;
4127 
4128     beginCommandBuffer(*m_device, *m_cmdBuffer);
4129 
4130     beforeRenderPass();
4131 
4132     if (!m_useDynamicRendering)
4133     {
4134         const VkRenderPassBeginInfo renderPassBeginInfo{
4135             VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
4136             DE_NULL,                                  // const void* pNext;
4137             renderPass,                               // VkRenderPass renderPass;
4138             frameBuffer,                              // VkFramebuffer framebuffer;
4139             renderArea,                               // VkRect2D renderArea;
4140             1u,                                       // uint32_t clearValueCount;
4141             &renderPassClearValue,                    // const VkClearValue* pClearValues;
4142         };
4143         cmdBeginRenderPass(*m_device, *m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE,
4144                            m_parameters.renderingType);
4145     }
4146 
4147     for (uint32_t subpassNdx = 0u; subpassNdx < subpassCount; subpassNdx++)
4148     {
4149         uint32_t firstVertexOffset = (subpassNdx < 4) ? 0u : m_squareCount * vertexPerPrimitive;
4150 
4151         m_device->cmdBindVertexBuffers(*m_cmdBuffer, 0u, DE_LENGTH_OF_ARRAY(vertexBuffers), vertexBuffers,
4152                                        vertexBufferOffsets);
4153         m_device->cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipelines[subpassNdx]);
4154 
4155 #ifndef CTS_USES_VULKANSC
4156         if (m_useDynamicRendering)
4157         {
4158             addRenderingSubpassDependencyIfRequired(subpassNdx);
4159 
4160             VkRenderingAttachmentInfoKHR colorAttachment{
4161                 vk::VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR, // VkStructureType sType;
4162                 DE_NULL,                                             // const void* pNext;
4163                 m_colorAttachment->getImageView(),                   // VkImageView imageView;
4164                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,            // VkImageLayout imageLayout;
4165                 VK_RESOLVE_MODE_NONE,                                // VkResolveModeFlagBits resolveMode;
4166                 DE_NULL,                                             // VkImageView resolveImageView;
4167                 VK_IMAGE_LAYOUT_UNDEFINED,                           // VkImageLayout resolveImageLayout;
4168                 VK_ATTACHMENT_LOAD_OP_LOAD,                          // VkAttachmentLoadOp loadOp;
4169                 vk::VK_ATTACHMENT_STORE_OP_STORE,                    // VkAttachmentStoreOp storeOp;
4170                 renderPassClearValue                                 // VkClearValue clearValue;
4171             };
4172 
4173             VkRenderingAttachmentInfoKHR dsAttachment{
4174                 VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR,  // VkStructureType sType;
4175                 DE_NULL,                                          // const void* pNext;
4176                 m_dsAttachment->getImageView(),                   // VkImageView imageView;
4177                 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout imageLayout;
4178                 VK_RESOLVE_MODE_NONE,                             // VkResolveModeFlagBits resolveMode;
4179                 DE_NULL,                                          // VkImageView resolveImageView;
4180                 VK_IMAGE_LAYOUT_UNDEFINED,                        // VkImageLayout resolveImageLayout;
4181                 VK_ATTACHMENT_LOAD_OP_LOAD,                       // VkAttachmentLoadOp loadOp;
4182                 VK_ATTACHMENT_STORE_OP_STORE,                     // VkAttachmentStoreOp storeOp;
4183                 makeClearValueDepthStencil(0.0f, 0)               // VkClearValue clearValue;
4184             };
4185 
4186             vk::VkRenderingInfoKHR renderingInfo{
4187                 vk::VK_STRUCTURE_TYPE_RENDERING_INFO_KHR,
4188                 DE_NULL,
4189                 0u,                                        // VkRenderingFlagsKHR flags;
4190                 renderArea,                                // VkRect2D renderArea;
4191                 m_parameters.extent.depth,                 // uint32_t layerCount;
4192                 m_parameters.viewMasks[subpassNdx],        // uint32_t viewMask;
4193                 1u,                                        // uint32_t colorAttachmentCount;
4194                 &colorAttachment,                          // const VkRenderingAttachmentInfoKHR* pColorAttachments;
4195                 (m_depthTest ? &dsAttachment : DE_NULL),   // const VkRenderingAttachmentInfoKHR* pDepthAttachment;
4196                 (m_stencilTest ? &dsAttachment : DE_NULL), // const VkRenderingAttachmentInfoKHR* pStencilAttachment;
4197             };
4198 
4199             m_device->cmdBeginRendering(*m_cmdBuffer, &renderingInfo);
4200         }
4201 #endif // CTS_USES_VULKANSC
4202 
4203         for (uint32_t drawNdx = 0u; drawNdx < drawCountPerSubpass; ++drawNdx)
4204             m_device->cmdDraw(*m_cmdBuffer, vertexPerPrimitive, 1u,
4205                               firstVertexOffset + (drawNdx + subpassNdx % m_squareCount) * vertexPerPrimitive, 0u);
4206 
4207 #ifndef CTS_USES_VULKANSC
4208         if (m_useDynamicRendering)
4209             endRendering(*m_device, *m_cmdBuffer);
4210         else
4211 #endif // CTS_USES_VULKANSC
4212             if (subpassNdx < subpassCount - 1u)
4213                 cmdNextSubpass(*m_device, *m_cmdBuffer, VK_SUBPASS_CONTENTS_INLINE, m_parameters.renderingType);
4214     }
4215 
4216     if (!m_useDynamicRendering)
4217         cmdEndRenderPass(*m_device, *m_cmdBuffer, m_parameters.renderingType);
4218 
4219     afterRenderPass();
4220 
4221     VK_CHECK(m_device->endCommandBuffer(*m_cmdBuffer));
4222     submitCommandsAndWait(*m_device, *m_logicalDevice, m_queue, *m_cmdBuffer);
4223 }
4224 
beforeRenderPass(void)4225 void MultiViewDepthStencilTestInstance::beforeRenderPass(void)
4226 {
4227     MultiViewRenderTestInstance::beforeRenderPass();
4228 
4229     const VkImageSubresourceRange subresourceRange = {
4230         VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, //VkImageAspectFlags aspectMask;
4231         0u,                                                      //uint32_t baseMipLevel;
4232         1u,                                                      //uint32_t levelCount;
4233         0u,                                                      //uint32_t baseArrayLayer;
4234         m_parameters.extent.depth,                               //uint32_t layerCount;
4235     };
4236     imageBarrier(*m_device, *m_cmdBuffer, m_dsAttachment->getImage(), subresourceRange, VK_IMAGE_LAYOUT_UNDEFINED,
4237                  VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0, VK_ACCESS_TRANSFER_WRITE_BIT,
4238                  VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
4239 
4240     const tcu::Vec4 baseColor     = getQuarterRefColor(0u, 0u, 0u, false);
4241     const float clearDepth        = baseColor[0];
4242     const VkClearValue clearValue = makeClearValueDepthStencil(clearDepth, 0);
4243 
4244     m_device->cmdClearDepthStencilImage(*m_cmdBuffer, m_dsAttachment->getImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
4245                                         &clearValue.depthStencil, 1, &subresourceRange);
4246 
4247     imageBarrier(*m_device, *m_cmdBuffer, m_dsAttachment->getImage(), subresourceRange,
4248                  VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
4249                  VK_ACCESS_TRANSFER_WRITE_BIT,
4250                  VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
4251                  VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT);
4252 }
4253 
afterRenderPass(void)4254 void MultiViewDepthStencilTestInstance::afterRenderPass(void)
4255 {
4256     MultiViewRenderTestInstance::afterRenderPass();
4257 
4258     const VkImageSubresourceRange dsSubresourceRange = {
4259         VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, //  VkImageAspectFlags aspectMask;
4260         0u,                                                      //  uint32_t baseMipLevel;
4261         1u,                                                      //  uint32_t levelCount;
4262         0u,                                                      //  uint32_t baseArrayLayer;
4263         m_parameters.extent.depth,                               //  uint32_t layerCount;
4264     };
4265 
4266     imageBarrier(*m_device, *m_cmdBuffer, m_dsAttachment->getImage(), dsSubresourceRange,
4267                  VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
4268                  VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
4269                  VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
4270 }
4271 
4272 class MultiViewMaskIterationTestInstance : public MultiViewRenderTestInstance
4273 {
4274 public:
4275     MultiViewMaskIterationTestInstance(Context &context, const TestParameters &parameters);
4276 
4277 protected:
4278     void beforeRender(const VkCommandBuffer cmdBuffer);
4279     void afterRender(const VkCommandBuffer cmdBuffer);
4280     tcu::TestStatus iterate(void) override;
4281 
4282     using ImageWithBufferPtr = std::unique_ptr<ImageWithBuffer>;
4283     ImageWithBufferPtr m_colorImage;
4284     tcu::IVec3 m_dim;
4285     uint32_t m_layerCount;
4286     VkImageSubresourceRange m_colorSRR;
4287     VkClearValue m_clearValue;
4288 };
4289 
MultiViewMaskIterationTestInstance(Context & context,const TestParameters & parameters)4290 MultiViewMaskIterationTestInstance::MultiViewMaskIterationTestInstance(Context &context,
4291                                                                        const TestParameters &parameters)
4292     : MultiViewRenderTestInstance(context, parameters)
4293 {
4294     m_dim        = tcu::IVec3(m_parameters.extent.width, m_parameters.extent.height, 1);
4295     m_layerCount = m_parameters.extent.depth;
4296     const auto colorUsage =
4297         (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
4298     m_colorSRR   = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, m_layerCount);
4299     m_colorImage = ImageWithBufferPtr(new ImageWithBuffer(*m_device, *m_logicalDevice, *m_allocator,
4300                                                           makeExtent3D(m_dim), m_parameters.colorFormat, colorUsage,
4301                                                           VK_IMAGE_TYPE_2D, m_colorSRR, m_layerCount));
4302     m_clearValue = makeClearValueColor(tcu::Vec4(0));
4303 }
4304 
beforeRender(const VkCommandBuffer cmdBuffer)4305 void MultiViewMaskIterationTestInstance::beforeRender(const VkCommandBuffer cmdBuffer)
4306 {
4307     imageBarrier(*m_device, cmdBuffer, m_colorImage->getImage(), m_colorSRR, VK_IMAGE_LAYOUT_UNDEFINED,
4308                  VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0, VK_ACCESS_TRANSFER_WRITE_BIT,
4309                  VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
4310 
4311     m_device->cmdClearColorImage(cmdBuffer, m_colorImage->getImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
4312                                  &m_clearValue.color, 1u, &m_colorSRR);
4313 
4314     imageBarrier(*m_device, cmdBuffer, m_colorImage->getImage(), m_colorSRR, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
4315                  VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ACCESS_TRANSFER_WRITE_BIT,
4316                  (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT),
4317                  VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
4318 }
4319 
afterRender(const VkCommandBuffer cmdBuffer)4320 void MultiViewMaskIterationTestInstance::afterRender(const VkCommandBuffer cmdBuffer)
4321 {
4322     imageBarrier(*m_device, cmdBuffer, m_colorImage->getImage(), m_colorSRR, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
4323                  VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
4324                  (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT),
4325                  VK_ACCESS_TRANSFER_READ_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
4326                  VK_PIPELINE_STAGE_TRANSFER_BIT);
4327 }
4328 
iterate(void)4329 tcu::TestStatus MultiViewMaskIterationTestInstance::iterate(void)
4330 {
4331     bool failure                = false;
4332     const uint32_t subpassCount = static_cast<uint32_t>(m_parameters.viewMasks.size());
4333     const auto fbExtent         = makeExtent3D(m_dim);
4334     const auto colorSRL         = makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, m_layerCount);
4335 
4336     map<VkShaderStageFlagBits, ShaderModuleSP> shaderModule;
4337     vector<VkPipelineShaderStageCreateInfo> shaderStageParams;
4338     madeShaderModule(shaderModule, shaderStageParams);
4339     const VkShaderModule vertexShaderModule = shaderModule[VK_SHADER_STAGE_VERTEX_BIT]->get();
4340     const VkShaderModule fragShaderModule   = shaderModule[VK_SHADER_STAGE_FRAGMENT_BIT]->get();
4341 
4342     const std::vector<VkViewport> viewports(1u, makeViewport(fbExtent));
4343     const std::vector<VkRect2D> scissors(1u, makeRect2D(fbExtent));
4344     const auto pipelineLayout = makePipelineLayout(*m_device, *m_logicalDevice, VK_NULL_HANDLE);
4345 
4346     const auto colorBlendAttState = makePipelineColorBlendAttachmentState(
4347         VK_FALSE, VK_BLEND_FACTOR_ZERO, VK_BLEND_FACTOR_ZERO, VK_BLEND_OP_ADD, VK_BLEND_FACTOR_ZERO,
4348         VK_BLEND_FACTOR_ZERO, VK_BLEND_OP_ADD,
4349         (VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT));
4350 
4351     const VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo = initVulkanStructure();
4352 
4353 #ifndef CTS_USES_VULKANSC
4354     VkRenderingAttachmentInfoKHR renderingAttInfo = {
4355         VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR, // VkStructureType sType;
4356         nullptr,                                         // const void* pNext;
4357         m_colorImage->getImageView(),                    // VkImageView imageView;
4358         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,        // VkImageLayout imageLayout;
4359         VK_RESOLVE_MODE_NONE,                            // VkResolveModeFlagBits resolveMode;
4360         VK_NULL_HANDLE,                                  // VkImageView resolveImageView;
4361         VK_IMAGE_LAYOUT_UNDEFINED,                       // VkImageLayout resolveImageLayout;
4362         VK_ATTACHMENT_LOAD_OP_LOAD,                      // VkAttachmentLoadOp loadOp;
4363         VK_ATTACHMENT_STORE_OP_STORE,                    // VkAttachmentStoreOp storeOp;
4364         m_clearValue,                                    // VkClearValue clearValue;
4365     };
4366 #endif
4367 
4368     for (uint32_t subpassNdx = 0u; subpassNdx < subpassCount; ++subpassNdx)
4369     {
4370         const auto layerMask = m_parameters.viewMasks[subpassNdx];
4371         Move<VkRenderPass> renderPass;
4372         Move<VkFramebuffer> frameBuffer;
4373 
4374         // FrameBuffer & renderPass
4375         if (m_parameters.renderingType != RENDERING_TYPE_DYNAMIC_RENDERING)
4376         {
4377             const std::vector<uint32_t> layerMasks(1u, layerMask);
4378             renderPass  = makeRenderPass(*m_device, *m_logicalDevice, m_parameters.colorFormat, layerMasks,
4379                                          m_parameters.renderingType);
4380             frameBuffer = makeFramebuffer(*m_device, *m_logicalDevice, *renderPass, m_colorImage->getImageView(),
4381                                           fbExtent.width, fbExtent.height);
4382         }
4383 #ifndef CTS_USES_VULKANSC
4384         const VkPipelineRenderingCreateInfo pipelineRenderingCreateInfo = {
4385             VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR, // VkStructureType sType;
4386             nullptr,                                              // const void* pNext;
4387             layerMask,                                            // uint32_t viewMask;
4388             1u,                                                   // uint32_t colorAttachmentCount;
4389             &m_parameters.colorFormat,                            // const VkFormat* pColorAttachmentFormats;
4390             VK_FORMAT_UNDEFINED,                                  // VkFormat depthAttachmentFormat;
4391             VK_FORMAT_UNDEFINED,                                  // VkFormat stencilAttachmentFormat;
4392         };
4393 #endif // CTS_USES_VULKANSC
4394         const std::vector<VkPipelineColorBlendAttachmentState> colorBlendStateVec(1u, colorBlendAttState);
4395 
4396         const VkPipelineColorBlendStateCreateInfo colorBlendStateCreateInfo = {
4397             VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
4398             nullptr,                                                  // const void* pNext;
4399             0u,                                                       // VkPipelineColorBlendStateCreateFlags flags;
4400             VK_FALSE,                                                 // VkBool32 logicOpEnable;
4401             VK_LOGIC_OP_CLEAR,                                        // VkLogicOp logicOp;
4402             de::sizeU32(colorBlendStateVec),                          // uint32_t attachmentCount;
4403             de::dataOrNull(colorBlendStateVec), // const VkPipelineColorBlendAttachmentState* pAttachments;
4404             {0.0f, 0.0f, 0.0f, 0.0f},           // float blendConstants[4];
4405         };
4406 
4407         const auto pipeline = vk::makeGraphicsPipeline(
4408             *m_device, *m_logicalDevice, pipelineLayout.get(), vertexShaderModule, VK_NULL_HANDLE, VK_NULL_HANDLE,
4409             VK_NULL_HANDLE, fragShaderModule, *renderPass, viewports, scissors, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0u,
4410             0u, &vertexInputStateCreateInfo, nullptr, nullptr, nullptr, &colorBlendStateCreateInfo, nullptr,
4411 #ifndef CTS_USES_VULKANSC
4412             (*renderPass == 0) ? &pipelineRenderingCreateInfo : VK_NULL_HANDLE
4413 #else
4414             VK_NULL_HANDLE
4415 #endif // CTS_USES_VULKANSC
4416         );
4417 
4418         CommandPoolWithBuffer cmd(*m_device, *m_logicalDevice, m_queueFamilyIndex);
4419         const auto cmdBuffer = cmd.cmdBuffer.get();
4420 
4421         beginCommandBuffer(*m_device, cmdBuffer);
4422 
4423         beforeRender(cmdBuffer);
4424 
4425         if (!m_useDynamicRendering)
4426         {
4427             const VkRect2D renderArea = {{0, 0}, {fbExtent.width, fbExtent.height}};
4428             const VkRenderPassBeginInfo renderPassBeginInfo{
4429                 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
4430                 DE_NULL,                                  // const void* pNext;
4431                 *renderPass,                              // VkRenderPass renderPass;
4432                 *frameBuffer,                             // VkFramebuffer framebuffer;
4433                 renderArea,                               // VkRect2D renderArea;
4434                 1u,                                       // uint32_t clearValueCount;
4435                 &m_clearValue,                            // const VkClearValue* pClearValues;
4436             };
4437             cmdBeginRenderPass(*m_device, cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE,
4438                                m_parameters.renderingType);
4439         }
4440 #ifndef CTS_USES_VULKANSC
4441         else
4442         {
4443             const VkRenderingInfoKHR renderingInfo = {
4444                 VK_STRUCTURE_TYPE_RENDERING_INFO_KHR, // VkStructureType sType;
4445                 nullptr,                              // const void* pNext;
4446                 0,                                    // VkRenderingFlags flags;
4447                 scissors.at(0u),                      // VkRect2D renderArea;
4448                 m_layerCount,                         // uint32_t m_layerCount;
4449                 layerMask,                            // uint32_t viewMask;
4450                 1u,                                   // uint32_t colorAttachmentCount;
4451                 &renderingAttInfo,                    // const VkRenderingAttachmentInfo* pColorAttachments;
4452                 DE_NULL,                              // const VkRenderingAttachmentInfo* pDepthAttachment;
4453                 DE_NULL,                              // const VkRenderingAttachmentInfo* pStencilAttachment;
4454             };
4455 
4456             m_device->cmdBeginRendering(cmdBuffer, &renderingInfo);
4457         }
4458 #endif // CTS_USES_VULKANSC
4459 
4460         m_device->cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get());
4461 
4462         m_device->cmdDraw(cmdBuffer, 3u, 1u, 0u, 0u);
4463 
4464         if (!m_useDynamicRendering)
4465             cmdEndRenderPass(*m_device, cmdBuffer, m_parameters.renderingType);
4466 #ifndef CTS_USES_VULKANSC
4467         else
4468             m_device->cmdEndRendering(cmdBuffer);
4469 #endif // CTS_USES_VULKANSC
4470 
4471         afterRender(cmdBuffer);
4472 
4473         // Copy all image contents to their verification buffers
4474         const auto copyRegion = makeBufferImageCopy(fbExtent, colorSRL);
4475         m_device->cmdCopyImageToBuffer(cmdBuffer, m_colorImage->getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
4476                                        m_colorImage->getBuffer(), 1u, &copyRegion);
4477 
4478         // Global barrier to synchronize verification buffers to host reads.
4479         {
4480             const auto transfer2HostBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
4481             cmdPipelineMemoryBarrier(*m_device, cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
4482                                      &transfer2HostBarrier);
4483         }
4484 
4485         endCommandBuffer(*m_device, cmdBuffer);
4486         submitCommandsAndWait(*m_device, *m_logicalDevice, m_queue, cmdBuffer);
4487 
4488         // Invalidate all allocations.
4489         invalidateAlloc(*m_device, *m_logicalDevice, m_colorImage->getBufferAllocation());
4490 
4491         // Verify all layers in all images.
4492         const auto colorTcuFormat = mapVkFormat(m_parameters.colorFormat);
4493         const auto colorPixelSize = tcu::getPixelSize(colorTcuFormat);
4494         const auto colorLayerSize = static_cast<size_t>(m_dim.x() * m_dim.y() * m_dim.z() * colorPixelSize);
4495 
4496         const tcu::UVec4 threshold(0u, 0u, 0u, 0u); // We expect exact results.
4497         auto &log = m_context.getTestContext().getLog();
4498 
4499         const auto dataPtr = reinterpret_cast<const char *>(m_colorImage->getBufferAllocation().getHostPtr());
4500 
4501         for (uint32_t layerIdx = 0u; layerIdx < m_layerCount; ++layerIdx)
4502         {
4503             const bool layerWritten = ((layerMask & (1 << layerIdx)) != 0u);
4504             const auto layerDataPtr = dataPtr + colorLayerSize * layerIdx;
4505             const tcu::ConstPixelBufferAccess layerAccess(colorTcuFormat, m_dim, layerDataPtr);
4506             const tcu::UVec4 expectedColor =
4507                 (layerWritten ? tcu::UVec4(layerIdx, 255u, 0, 255u) // Needs to match frag shader.
4508                                 :
4509                                 tcu::UVec4(0u, 0u, 0u, 0u));
4510             const std::string logImgName = "ColorAttachment" + std::to_string(0) + "-Subpass" +
4511                                            std::to_string(subpassNdx) + "-Layer" + std::to_string(layerIdx);
4512             tcu::TextureLevel refLevel(colorTcuFormat, m_dim.x(), m_dim.y(), m_dim.z());
4513             tcu::PixelBufferAccess refAccess = refLevel.getAccess();
4514 
4515             tcu::clear(refAccess, expectedColor);
4516 
4517             if (!tcu::intThresholdCompare(log, logImgName.c_str(), "", refAccess, layerAccess, threshold,
4518                                           tcu::COMPARE_LOG_ON_ERROR))
4519                 failure = true;
4520         }
4521     }
4522 
4523     if (failure)
4524         return tcu::TestStatus::fail("Invalid value found in verification buffers; check log for details");
4525 
4526     return tcu::TestStatus::pass("Pass");
4527 }
4528 
4529 class MultiViewRenderTestsCase : public vkt::TestCase
4530 {
4531 public:
MultiViewRenderTestsCase(tcu::TestContext & context,const char * name,const TestParameters & parameters)4532     MultiViewRenderTestsCase(tcu::TestContext &context, const char *name, const TestParameters &parameters)
4533         : TestCase(context, name)
4534         , m_parameters(parameters)
4535     {
4536         DE_ASSERT(m_parameters.extent.width == m_parameters.extent.height);
4537     }
4538 
4539 private:
4540     const TestParameters m_parameters;
4541 
createInstance(vkt::Context & context) const4542     vkt::TestInstance *createInstance(vkt::Context &context) const
4543     {
4544         if (TEST_TYPE_INPUT_ATTACHMENTS == m_parameters.viewIndex ||
4545             TEST_TYPE_INPUT_ATTACHMENTS_GEOMETRY == m_parameters.viewIndex)
4546             return new MultiViewAttachmentsTestInstance(context, m_parameters);
4547 
4548         if (TEST_TYPE_INSTANCED_RENDERING == m_parameters.viewIndex)
4549             return new MultiViewInstancedTestInstance(context, m_parameters);
4550 
4551         if (TEST_TYPE_INPUT_RATE_INSTANCE == m_parameters.viewIndex)
4552             return new MultiViewInputRateInstanceTestInstance(context, m_parameters);
4553 
4554         if (TEST_TYPE_DRAW_INDIRECT == m_parameters.viewIndex ||
4555             TEST_TYPE_DRAW_INDIRECT_INDEXED == m_parameters.viewIndex)
4556             return new MultiViewDrawIndirectTestInstance(context, m_parameters);
4557 
4558         if (TEST_TYPE_CLEAR_ATTACHMENTS == m_parameters.viewIndex)
4559             return new MultiViewClearAttachmentsTestInstance(context, m_parameters);
4560 
4561         if (TEST_TYPE_SECONDARY_CMD_BUFFER == m_parameters.viewIndex ||
4562             TEST_TYPE_SECONDARY_CMD_BUFFER_GEOMETRY == m_parameters.viewIndex ||
4563             TEST_TYPE_NESTED_CMD_BUFFER == m_parameters.viewIndex)
4564             return new MultiViewSecondaryCommandBufferTestInstance(context, m_parameters);
4565 
4566         if (TEST_TYPE_POINT_SIZE == m_parameters.viewIndex)
4567             return new MultiViewPointSizeTestInstance(context, m_parameters);
4568 
4569         if (TEST_TYPE_MULTISAMPLE == m_parameters.viewIndex)
4570             return new MultiViewMultsampleTestInstance(context, m_parameters);
4571 
4572         if (TEST_TYPE_QUERIES == m_parameters.viewIndex || TEST_TYPE_NON_PRECISE_QUERIES == m_parameters.viewIndex ||
4573             TEST_TYPE_NON_PRECISE_QUERIES_WITH_AVAILABILITY == m_parameters.viewIndex)
4574             return new MultiViewQueriesTestInstance(context, m_parameters);
4575 
4576         if (TEST_TYPE_VIEW_MASK == m_parameters.viewIndex || TEST_TYPE_VIEW_INDEX_IN_VERTEX == m_parameters.viewIndex ||
4577             TEST_TYPE_VIEW_INDEX_IN_FRAGMENT == m_parameters.viewIndex ||
4578             TEST_TYPE_VIEW_INDEX_IN_GEOMETRY == m_parameters.viewIndex ||
4579             TEST_TYPE_VIEW_INDEX_IN_TESELLATION == m_parameters.viewIndex ||
4580             TEST_TYPE_DRAW_INDEXED == m_parameters.viewIndex)
4581             return new MultiViewRenderTestInstance(context, m_parameters);
4582         if (TEST_TYPE_VIEW_MASK_ITERATION == m_parameters.viewIndex)
4583             return new MultiViewMaskIterationTestInstance(context, m_parameters);
4584         if (TEST_TYPE_READBACK_WITH_IMPLICIT_CLEAR == m_parameters.viewIndex ||
4585             TEST_TYPE_READBACK_WITH_EXPLICIT_CLEAR == m_parameters.viewIndex)
4586             return new MultiViewReadbackTestInstance(context, m_parameters);
4587 
4588         if (TEST_TYPE_DEPTH == m_parameters.viewIndex || TEST_TYPE_DEPTH_DIFFERENT_RANGES == m_parameters.viewIndex ||
4589             TEST_TYPE_STENCIL == m_parameters.viewIndex)
4590             return new MultiViewDepthStencilTestInstance(context, m_parameters);
4591 
4592         TCU_THROW(InternalError, "Unknown test type");
4593     }
4594 
checkSupport(Context & context) const4595     virtual void checkSupport(Context &context) const
4596     {
4597         if (m_parameters.geometryShaderNeeded())
4598             context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
4599 
4600         if (m_parameters.renderingType == RENDERING_TYPE_RENDERPASS2)
4601             context.requireDeviceFunctionality("VK_KHR_create_renderpass2");
4602 
4603         if (m_parameters.renderingType == RENDERING_TYPE_DYNAMIC_RENDERING)
4604             context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
4605 
4606         context.requireDeviceFunctionality("VK_KHR_multiview");
4607 
4608         if (m_parameters.viewIndex == TEST_TYPE_DEPTH_DIFFERENT_RANGES)
4609             context.requireDeviceFunctionality("VK_EXT_depth_range_unrestricted");
4610         if (m_parameters.viewIndex == TEST_TYPE_QUERIES)
4611             context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_OCCLUSION_QUERY_PRECISE);
4612         if (m_parameters.viewIndex == TEST_TYPE_NESTED_CMD_BUFFER)
4613             context.requireDeviceFunctionality("VK_EXT_nested_command_buffer");
4614 
4615 #ifdef CTS_USES_VULKANSC
4616         const InstanceInterface &instance                       = context.getInstanceInterface();
4617         const VkPhysicalDevice physicalDevice                   = context.getPhysicalDevice();
4618         VkPhysicalDeviceMultiviewProperties multiviewProperties = {
4619             VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES, //VkStructureType sType;
4620             DE_NULL,                                                //void* pNext;
4621             0u,                                                     //uint32_t maxMultiviewViewCount;
4622             0u                                                      //uint32_t maxMultiviewInstanceIndex;
4623         };
4624 
4625         VkPhysicalDeviceProperties2 propertiesDeviceProperties2;
4626         propertiesDeviceProperties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
4627         propertiesDeviceProperties2.pNext = &multiviewProperties;
4628 
4629         instance.getPhysicalDeviceProperties2(physicalDevice, &propertiesDeviceProperties2);
4630 
4631         if (multiviewProperties.maxMultiviewViewCount < m_parameters.viewMasks.size())
4632             TCU_THROW(NotSupportedError, "maxMultiviewViewCount is less than required by test");
4633 #endif // CTS_USES_VULKANSC
4634     }
4635 
initPrograms(SourceCollections & programCollection) const4636     void initPrograms(SourceCollections &programCollection) const
4637     {
4638         // Create vertex shader
4639         if (TEST_TYPE_INSTANCED_RENDERING == m_parameters.viewIndex)
4640         {
4641             std::ostringstream source;
4642             source << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
4643                    << "#extension GL_EXT_multiview : enable\n"
4644                    << "layout(location = 0) in highp vec4 in_position;\n"
4645                    << "layout(location = 1) in vec4 in_color;\n"
4646                    << "layout(location = 0) out vec4 out_color;\n"
4647                    << "void main (void)\n"
4648                    << "{\n"
4649                    << "    int modInstance = gl_InstanceIndex % 4;\n"
4650                    << "    int instance    = gl_InstanceIndex + 1;\n"
4651                    << "    gl_Position = in_position;\n"
4652                    << "    if (modInstance == 1)\n"
4653                    << "        gl_Position = in_position + vec4(0.0f, 1.0f, 0.0f, 0.0f);\n"
4654                    << "    if (modInstance == 2)\n"
4655                    << "        gl_Position = in_position + vec4(1.0f, 0.0f, 0.0f, 0.0f);\n"
4656                    << "    if (modInstance == 3)\n"
4657                    << "        gl_Position =  in_position + vec4(1.0f, 1.0f, 0.0f, 0.0f);\n"
4658                    << "    out_color = in_color + vec4(0.0f, gl_ViewIndex * 0.10f, instance * 0.10f, 0.0f);\n"
4659                    << "}\n";
4660             programCollection.glslSources.add("vertex") << glu::VertexSource(source.str());
4661         }
4662         else if (TEST_TYPE_INPUT_RATE_INSTANCE == m_parameters.viewIndex)
4663         {
4664             std::ostringstream source;
4665             source << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
4666                    << "#extension GL_EXT_multiview : enable\n"
4667                    << "layout(location = 0) in highp vec4 in_position;\n"
4668                    << "layout(location = 1) in vec4 in_color;\n"
4669                    << "layout(location = 0) out vec4 out_color;\n"
4670                    << "void main (void)\n"
4671                    << "{\n"
4672                    << "    int instance = gl_InstanceIndex + 1;\n"
4673                    << "    gl_Position = in_position;\n"
4674                    << "    if (gl_VertexIndex == 1)\n"
4675                    << "        gl_Position.y += 1.0f;\n"
4676                    << "    else if (gl_VertexIndex == 2)\n"
4677                    << "        gl_Position.x += 1.0f;\n"
4678                    << "    else if (gl_VertexIndex == 3)\n"
4679                    << "    {\n"
4680                    << "        gl_Position.x += 1.0f;\n"
4681                    << "        gl_Position.y += 1.0f;\n"
4682                    << "    }\n"
4683                    << "    out_color = in_color + vec4(0.0f, gl_ViewIndex * 0.10f, instance * 0.10f, 0.0f);\n"
4684                    << "}\n";
4685             programCollection.glslSources.add("vertex") << glu::VertexSource(source.str());
4686         }
4687         else if (TEST_TYPE_POINT_SIZE == m_parameters.viewIndex)
4688         {
4689             std::ostringstream source;
4690             source << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
4691                    << "#extension GL_EXT_multiview : enable\n"
4692                    << "layout(location = 0) in highp vec4 in_position;\n"
4693                    << "layout(location = 1) in highp vec4 in_color;\n"
4694                    << "layout(location = 0) out vec4 out_color;\n"
4695                    << "void main (void)\n"
4696                    << "{\n"
4697                    << "    gl_Position = in_position;\n"
4698                    << "    if (gl_ViewIndex == 0)\n"
4699                    << "        gl_PointSize = " << de::floatToString(static_cast<float>(TEST_POINT_SIZE_WIDE), 1)
4700                    << "f;\n"
4701                    << "    else\n"
4702                    << "        gl_PointSize = " << de::floatToString(static_cast<float>(TEST_POINT_SIZE_SMALL), 1)
4703                    << "f;\n"
4704                    << "    out_color = in_color;\n"
4705                    << "}\n";
4706             programCollection.glslSources.add("vertex") << glu::VertexSource(source.str());
4707         }
4708         else if (TEST_TYPE_VIEW_MASK_ITERATION == m_parameters.viewIndex)
4709         {
4710             std::ostringstream source;
4711             source << "#version 460\n"
4712                    << "#extension GL_ARB_shader_viewport_layer_array : enable\n"
4713                    << "vec2 positions[3] = vec2[](\n"
4714                    << "    vec2(-1.0, -1.0),\n"
4715                    << "    vec2(-1.0,  3.0),\n"
4716                    << "    vec2( 3.0, -1.0)\n"
4717                    << ");\n"
4718                    << "void main() {\n"
4719                    << "    gl_Position = vec4(positions[gl_VertexIndex % 3], 1.0, 1.0);\n"
4720                    << "}\n";
4721             {
4722                 const auto src = source.str();
4723                 const vk::ShaderBuildOptions spv15Opts(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_5, 0u,
4724                                                        false);
4725 
4726                 programCollection.glslSources.add("vert-spv10") << glu::VertexSource(src);
4727                 programCollection.glslSources.add("vert-spv15") << glu::VertexSource(src) << spv15Opts;
4728             }
4729         }
4730         else
4731         {
4732             const bool generateColor = (TEST_TYPE_VIEW_INDEX_IN_VERTEX == m_parameters.viewIndex) ||
4733                                        (TEST_TYPE_DRAW_INDIRECT == m_parameters.viewIndex) ||
4734                                        (TEST_TYPE_DRAW_INDIRECT_INDEXED == m_parameters.viewIndex) ||
4735                                        (TEST_TYPE_CLEAR_ATTACHMENTS == m_parameters.viewIndex);
4736             std::ostringstream source;
4737             source << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
4738                    << "#extension GL_EXT_multiview : enable\n"
4739                    << "layout(location = 0) in highp vec4 in_position;\n"
4740                    << "layout(location = 1) in vec4 in_color;\n"
4741                    << "layout(location = 0) out vec4 out_color;\n"
4742                    << "void main (void)\n"
4743                    << "{\n"
4744                    << "    gl_Position = in_position;\n";
4745             if (generateColor)
4746                 source << "    out_color = in_color + vec4(0.0, gl_ViewIndex * 0.10f, 0.0, 0.0);\n";
4747             else
4748                 source << "    out_color = in_color;\n";
4749             source << "}\n";
4750             programCollection.glslSources.add("vertex") << glu::VertexSource(source.str());
4751         }
4752 
4753         if (TEST_TYPE_VIEW_INDEX_IN_TESELLATION == m_parameters.viewIndex)
4754         { // Tessellation control & evaluation
4755             std::ostringstream source_tc;
4756             source_tc << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
4757                       << "#extension GL_EXT_multiview : enable\n"
4758                       << "#extension GL_EXT_tessellation_shader : require\n"
4759                       << "layout(vertices = 4) out;\n"
4760                       << "layout(location = 0) in vec4 in_color[];\n"
4761                       << "layout(location = 0) out vec4 out_color[];\n"
4762                       << "\n"
4763                       << "void main (void)\n"
4764                       << "{\n"
4765                       << "    if ( gl_InvocationID == 0 )\n"
4766                       << "    {\n"
4767                       << "        gl_TessLevelInner[0] = 4.0f;\n"
4768                       << "        gl_TessLevelInner[1] = 4.0f;\n"
4769                       << "        gl_TessLevelOuter[0] = 4.0f;\n"
4770                       << "        gl_TessLevelOuter[1] = 4.0f;\n"
4771                       << "        gl_TessLevelOuter[2] = 4.0f;\n"
4772                       << "        gl_TessLevelOuter[3] = 4.0f;\n"
4773                       << "    }\n"
4774                       << "    out_color[gl_InvocationID] = in_color[gl_InvocationID];\n"
4775                       << "    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
4776                       << "}\n";
4777             programCollection.glslSources.add("tessellation_control")
4778                 << glu::TessellationControlSource(source_tc.str());
4779 
4780             std::ostringstream source_te;
4781             source_te
4782                 << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
4783                 << "#extension GL_EXT_multiview : enable\n"
4784                 << "#extension GL_EXT_tessellation_shader : require\n"
4785                 << "layout( quads, equal_spacing, ccw ) in;\n"
4786                 << "layout(location = 0) in vec4 in_color[];\n"
4787                 << "layout(location = 0) out vec4 out_color;\n"
4788                 << "void main (void)\n"
4789                 << "{\n"
4790                 << "    const float u = gl_TessCoord.x;\n"
4791                 << "    const float v = gl_TessCoord.y;\n"
4792                 << "    const float w = gl_TessCoord.z;\n"
4793                 << "    gl_Position = (1 - u) * (1 - v) * gl_in[0].gl_Position +(1 - u) * v * gl_in[1].gl_Position "
4794                    "+ u * (1 - v) * gl_in[2].gl_Position + u * v * gl_in[3].gl_Position;\n"
4795                 << "    out_color = in_color[0]+ vec4(0.0, gl_ViewIndex * 0.10f, 0.0, 0.0);\n"
4796                 << "}\n";
4797             programCollection.glslSources.add("tessellation_evaluation")
4798                 << glu::TessellationEvaluationSource(source_te.str());
4799         }
4800 
4801         if (m_parameters.geometryShaderNeeded())
4802         { // Geometry Shader
4803             std::ostringstream source;
4804             source << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
4805                    << "#extension GL_EXT_multiview : enable\n"
4806                    << "layout(triangles) in;\n"
4807                    << "layout(triangle_strip, max_vertices = 16) out;\n"
4808                    << "layout(location = 0) in vec4 in_color[];\n"
4809                    << "layout(location = 0) out vec4 out_color;\n"
4810                    << "void main (void)\n"
4811                    << "{\n"
4812                    << "    out_color = in_color[0] + vec4(0.0, gl_ViewIndex * 0.10f, 0.0, 0.0);\n"
4813                    << "    gl_Position = gl_in[0].gl_Position;\n"
4814                    << "    EmitVertex();\n"
4815                    << "    out_color = in_color[0] + vec4(0.0, gl_ViewIndex * 0.10f, 0.0, 0.0);\n"
4816                    << "    gl_Position = gl_in[1].gl_Position;\n"
4817                    << "    EmitVertex();\n"
4818                    << "    out_color = in_color[0] + vec4(0.0, gl_ViewIndex * 0.10f, 0.0, 0.0);\n"
4819                    << "    gl_Position = gl_in[2].gl_Position;\n"
4820                    << "    EmitVertex();\n"
4821                    << "    out_color = in_color[0] + vec4(0.0, gl_ViewIndex * 0.10f, 0.0, 0.0);\n"
4822                    << "    gl_Position = vec4(gl_in[2].gl_Position.x, gl_in[1].gl_Position.y, 1.0, 1.0);\n"
4823                    << "    EmitVertex();\n"
4824                    << "    EndPrimitive();\n"
4825                    << "}\n";
4826             programCollection.glslSources.add("geometry") << glu::GeometrySource(source.str());
4827         }
4828 
4829         if (TEST_TYPE_INPUT_ATTACHMENTS == m_parameters.viewIndex)
4830         { // Create fragment shader read/write attachment
4831             std::ostringstream source;
4832             source << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
4833                    << "#extension GL_EXT_multiview : enable\n"
4834                    << "layout(location = 0) in vec4 in_color;\n"
4835                    << "layout(location = 0) out vec4 out_color;\n"
4836                    << "layout(input_attachment_index = 0, set=0, binding=0) uniform highp subpassInput "
4837                       "in_color_attachment;\n"
4838                    << "void main()\n"
4839                    << "{\n"
4840                    << "    out_color = vec4(subpassLoad(in_color_attachment));\n"
4841                    << "}\n";
4842             programCollection.glslSources.add("fragment") << glu::FragmentSource(source.str());
4843         }
4844         else if (TEST_TYPE_VIEW_MASK_ITERATION == m_parameters.viewIndex)
4845         {
4846             std::ostringstream source;
4847             source << "#version 460\n"
4848                    << "#extension "
4849                    << "GL_EXT_multiview"
4850                    << " : enable\n"
4851                    << "layout (location=" << 0 << ") out uvec4 color;\n"
4852                    << "void main (void) {\n"
4853                    << "    const uint layerIndex = uint(gl_ViewIndex);\n"
4854                    << "    color = uvec4(layerIndex, 255, " << 0 << ", 255);\n"
4855                    << "}\n";
4856             programCollection.glslSources.add("view_mask_iteration") << glu::FragmentSource(source.str());
4857         }
4858         else
4859         { // Create fragment shader
4860             std::ostringstream source;
4861             source << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
4862                    << "#extension GL_EXT_multiview : enable\n"
4863                    << "layout(location = 0) in vec4 in_color;\n"
4864                    << "layout(location = 0) out vec4 out_color;\n"
4865                    << "void main()\n"
4866                    << "{\n";
4867             if (TEST_TYPE_VIEW_INDEX_IN_FRAGMENT == m_parameters.viewIndex ||
4868                 TEST_TYPE_SECONDARY_CMD_BUFFER == m_parameters.viewIndex ||
4869                 TEST_TYPE_NESTED_CMD_BUFFER == m_parameters.viewIndex)
4870                 source << "    out_color = in_color + vec4(0.0, gl_ViewIndex * 0.10f, 0.0, 0.0);\n";
4871             else
4872                 source << "    out_color = in_color;\n";
4873             source << "}\n";
4874             programCollection.glslSources.add("fragment") << glu::FragmentSource(source.str());
4875         }
4876     }
4877 };
4878 } // namespace
4879 
createViewMasksName(const std::vector<uint32_t> & viewMasks)4880 static std::string createViewMasksName(const std::vector<uint32_t> &viewMasks)
4881 {
4882     std::ostringstream masks;
4883 
4884     for (size_t ndx = 0u; ndx < viewMasks.size(); ++ndx)
4885     {
4886         masks << viewMasks[ndx];
4887         if (viewMasks.size() - 1 != ndx)
4888             masks << "_";
4889     }
4890 
4891     return masks.str();
4892 }
4893 
tripleDepthStencilMasks(std::vector<uint32_t> & baseMasks)4894 static std::vector<uint32_t> tripleDepthStencilMasks(std::vector<uint32_t> &baseMasks)
4895 {
4896     std::vector<uint32_t> tripledMasks(baseMasks);
4897     std::vector<uint32_t> partBMasks;
4898 
4899     // a,b,c,d  =>  b,c,d,a
4900     partBMasks.insert(partBMasks.end(), baseMasks.begin() + 1, baseMasks.end());
4901     partBMasks.push_back(baseMasks[0]);
4902 
4903     tripledMasks.insert(tripledMasks.end(), partBMasks.begin(), partBMasks.end());
4904     tripledMasks.insert(tripledMasks.end(), partBMasks.begin(), partBMasks.end());
4905 
4906     return tripledMasks;
4907 }
4908 
multiViewRenderCreateTests(tcu::TestCaseGroup * group)4909 void multiViewRenderCreateTests(tcu::TestCaseGroup *group)
4910 {
4911     const uint32_t testCaseCount            = 7u;
4912     const string shaderName[TEST_TYPE_LAST] = {
4913         "masks",
4914         "vertex_shader",
4915         "fragment_shader",
4916         "geometry_shader",
4917         "tessellation_shader",
4918         "input_attachments",
4919         "input_attachments_geometry",
4920         "instanced",
4921         "input_instance",
4922         "draw_indirect",
4923         "draw_indirect_indexed",
4924         "draw_indexed",
4925         "clear_attachments",
4926         "secondary_cmd_buffer",
4927         "secondary_cmd_buffer_geometry",
4928         "point_size",
4929         "multisample",
4930         "queries",
4931         "non_precise_queries",
4932         "non_precise_queries_with_availability",
4933         "readback_implicit_clear",
4934         "readback_explicit_clear",
4935         "depth",
4936         "depth_different_ranges",
4937         "stencil",
4938         "view_mask_iteration",
4939         "nested_cmd_buffer",
4940     };
4941     const VkExtent3D extent3D[testCaseCount] = {
4942         {16u, 16u, 4u}, {64u, 64u, 8u}, {128u, 128u, 4u}, {32u, 32u, 5u},
4943         {64u, 64u, 6u}, {32u, 32u, 4u}, {16u, 16u, 10u},
4944     };
4945     vector<uint32_t> viewMasks[testCaseCount];
4946 
4947     viewMasks[0].push_back(15u); //1111
4948 
4949     viewMasks[1].push_back(8u); //1000
4950 
4951     viewMasks[2].push_back(1u); //0001
4952     viewMasks[2].push_back(2u); //0010
4953     viewMasks[2].push_back(4u); //0100
4954     viewMasks[2].push_back(8u); //1000
4955 
4956     viewMasks[3].push_back(15u); //1111
4957     viewMasks[3].push_back(15u); //1111
4958     viewMasks[3].push_back(15u); //1111
4959     viewMasks[3].push_back(15u); //1111
4960 
4961     viewMasks[4].push_back(8u); //1000
4962     viewMasks[4].push_back(1u); //0001
4963     viewMasks[4].push_back(1u); //0001
4964     viewMasks[4].push_back(8u); //1000
4965 
4966     viewMasks[5].push_back(5u);  //0101
4967     viewMasks[5].push_back(10u); //1010
4968     viewMasks[5].push_back(5u);  //0101
4969     viewMasks[5].push_back(10u); //1010
4970 
4971     const uint32_t minSupportedMultiviewViewCount = 6u;
4972     const uint32_t maxViewMask                    = (1u << minSupportedMultiviewViewCount) - 1u;
4973 
4974     for (uint32_t mask = 1u; mask <= maxViewMask; mask = mask << 1u)
4975         viewMasks[testCaseCount - 1].push_back(mask);
4976 
4977     vector<uint32_t> depthStencilMasks;
4978 
4979     depthStencilMasks.push_back(3u);  // 0011
4980     depthStencilMasks.push_back(6u);  // 0110
4981     depthStencilMasks.push_back(12u); // 1100
4982     depthStencilMasks.push_back(9u);  // 1001
4983 
4984 #ifndef CTS_USES_VULKANSC
4985     int numberOfRenderingTypes = 3;
4986 #else
4987     int numberOfRenderingTypes = 2;
4988 #endif // CTS_USES_VULKANSC
4989 
4990     for (int renderPassTypeNdx = 0; renderPassTypeNdx < numberOfRenderingTypes; ++renderPassTypeNdx)
4991     {
4992         RenderingType renderPassType(RENDERING_TYPE_RENDERPASS_LEGACY);
4993         MovePtr<tcu::TestCaseGroup> targetGroup(DE_NULL);
4994         tcu::TestCaseGroup *targetGroupPtr(group);
4995 
4996         if (renderPassTypeNdx == 1)
4997         {
4998             renderPassType = RENDERING_TYPE_RENDERPASS2;
4999             targetGroup = MovePtr<tcu::TestCaseGroup>(new tcu::TestCaseGroup(group->getTestContext(), "renderpass2"));
5000             targetGroupPtr = targetGroup.get();
5001         }
5002         else if (renderPassTypeNdx == 2)
5003         {
5004             renderPassType = RENDERING_TYPE_DYNAMIC_RENDERING;
5005             targetGroup =
5006                 MovePtr<tcu::TestCaseGroup>(new tcu::TestCaseGroup(group->getTestContext(), "dynamic_rendering"));
5007             targetGroupPtr = targetGroup.get();
5008         }
5009 
5010         tcu::TestContext &testCtx(targetGroupPtr->getTestContext());
5011         // ViewIndex rendering tests.
5012         MovePtr<tcu::TestCaseGroup> groupViewIndex(new tcu::TestCaseGroup(testCtx, "index"));
5013 
5014         for (int testTypeNdx = TEST_TYPE_VIEW_MASK; testTypeNdx < TEST_TYPE_LAST; ++testTypeNdx)
5015         {
5016             MovePtr<tcu::TestCaseGroup> groupShader(new tcu::TestCaseGroup(testCtx, shaderName[testTypeNdx].c_str()));
5017             const TestType testType = static_cast<TestType>(testTypeNdx);
5018             const VkSampleCountFlagBits sampleCountFlags =
5019                 (testType == TEST_TYPE_MULTISAMPLE) ? VK_SAMPLE_COUNT_4_BIT : VK_SAMPLE_COUNT_1_BIT;
5020             VkFormat colorFormat;
5021 
5022             if (testType == TEST_TYPE_MULTISAMPLE)
5023                 colorFormat = VK_FORMAT_R32G32B32A32_SFLOAT;
5024             else if (testType == TEST_TYPE_VIEW_MASK_ITERATION)
5025                 colorFormat = VK_FORMAT_R8G8B8A8_UINT;
5026             else
5027                 colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
5028 
5029             // subpassLoad can't be used with dynamic rendering
5030             if ((testTypeNdx == TEST_TYPE_INPUT_ATTACHMENTS) && (renderPassType == RENDERING_TYPE_DYNAMIC_RENDERING))
5031                 continue;
5032 
5033             if (testTypeNdx == TEST_TYPE_VIEW_MASK_ITERATION)
5034             {
5035                 for (uint32_t testCaseNdx = 0u; testCaseNdx < testCaseCount; ++testCaseNdx)
5036                 {
5037                     const TestParameters parameters = {extent3D[testCaseNdx],
5038                                                        viewMasks[testCaseNdx],
5039                                                        testType,
5040                                                        sampleCountFlags,
5041                                                        colorFormat,
5042                                                        QUERY_TYPE_GET_QUERY_POOL_RESULTS,
5043                                                        renderPassType};
5044                     const std::string testName      = createViewMasksName(parameters.viewMasks);
5045 
5046                     groupShader->addChild(new MultiViewRenderTestsCase(testCtx, testName.c_str(), parameters));
5047                 }
5048             }
5049             else
5050             {
5051                 for (int queryTypeNdx = 0; queryTypeNdx < 2; ++queryTypeNdx)
5052                 {
5053                     const std::string queryTestName =
5054                         queryTypeNdx == 0 ? "get_query_pool_results" : "cmd_copy_query_pool_results";
5055                     const auto queryType =
5056                         queryTypeNdx == 0 ? QUERY_TYPE_GET_QUERY_POOL_RESULTS : QUERY_TYPE_CMD_COPY_QUERY_POOL_RESULTS;
5057                     MovePtr<tcu::TestCaseGroup> queryTypeGroup(new tcu::TestCaseGroup(testCtx, queryTestName.c_str()));
5058 
5059                     if (testTypeNdx == TEST_TYPE_DEPTH || testTypeNdx == TEST_TYPE_DEPTH_DIFFERENT_RANGES ||
5060                         testTypeNdx == TEST_TYPE_STENCIL)
5061                     {
5062                         const VkExtent3D dsTestExtent3D = {64u, 64u, 4u};
5063                         const TestParameters parameters = {dsTestExtent3D, tripleDepthStencilMasks(depthStencilMasks),
5064                                                            testType,       sampleCountFlags,
5065                                                            colorFormat,    queryType,
5066                                                            renderPassType};
5067                         const std::string testName      = createViewMasksName(parameters.viewMasks);
5068 
5069                         queryTypeGroup->addChild(new MultiViewRenderTestsCase(testCtx, testName.c_str(), parameters));
5070                     }
5071                     else
5072                     {
5073                         for (uint32_t testCaseNdx = 0u; testCaseNdx < testCaseCount; ++testCaseNdx)
5074                         {
5075                             const TestParameters parameters = {extent3D[testCaseNdx],
5076                                                                viewMasks[testCaseNdx],
5077                                                                testType,
5078                                                                sampleCountFlags,
5079                                                                colorFormat,
5080                                                                queryType,
5081                                                                renderPassType};
5082                             const std::string testName      = createViewMasksName(parameters.viewMasks);
5083 
5084                             queryTypeGroup->addChild(
5085                                 new MultiViewRenderTestsCase(testCtx, testName.c_str(), parameters));
5086                         }
5087 
5088                         // maxMultiviewViewCount case
5089                         {
5090                             const VkExtent3D incompleteExtent3D = {16u, 16u, 0u};
5091                             const vector<uint32_t> unusedMasks;
5092                             const TestParameters parameters = {incompleteExtent3D, unusedMasks, testType,
5093                                                                sampleCountFlags,   colorFormat, queryType,
5094                                                                renderPassType};
5095 
5096                             queryTypeGroup->addChild(
5097                                 new MultiViewRenderTestsCase(testCtx, "max_multi_view_view_count", parameters));
5098                         }
5099                     }
5100                     groupShader->addChild(queryTypeGroup.release());
5101                 }
5102             }
5103 
5104             switch (testType)
5105             {
5106             case TEST_TYPE_VIEW_MASK:
5107             case TEST_TYPE_INPUT_ATTACHMENTS:
5108             case TEST_TYPE_INPUT_ATTACHMENTS_GEOMETRY:
5109             case TEST_TYPE_INSTANCED_RENDERING:
5110             case TEST_TYPE_INPUT_RATE_INSTANCE:
5111             case TEST_TYPE_DRAW_INDIRECT:
5112             case TEST_TYPE_DRAW_INDIRECT_INDEXED:
5113             case TEST_TYPE_DRAW_INDEXED:
5114             case TEST_TYPE_CLEAR_ATTACHMENTS:
5115             case TEST_TYPE_SECONDARY_CMD_BUFFER:
5116             case TEST_TYPE_SECONDARY_CMD_BUFFER_GEOMETRY:
5117             case TEST_TYPE_POINT_SIZE:
5118             case TEST_TYPE_MULTISAMPLE:
5119             case TEST_TYPE_QUERIES:
5120             case TEST_TYPE_NON_PRECISE_QUERIES:
5121             case TEST_TYPE_NON_PRECISE_QUERIES_WITH_AVAILABILITY:
5122             case TEST_TYPE_READBACK_WITH_IMPLICIT_CLEAR:
5123             case TEST_TYPE_READBACK_WITH_EXPLICIT_CLEAR:
5124             case TEST_TYPE_DEPTH:
5125             case TEST_TYPE_DEPTH_DIFFERENT_RANGES:
5126             case TEST_TYPE_STENCIL:
5127             case TEST_TYPE_VIEW_MASK_ITERATION:
5128             case TEST_TYPE_NESTED_CMD_BUFFER:
5129                 targetGroupPtr->addChild(groupShader.release());
5130                 break;
5131             case TEST_TYPE_VIEW_INDEX_IN_VERTEX:
5132             case TEST_TYPE_VIEW_INDEX_IN_FRAGMENT:
5133             case TEST_TYPE_VIEW_INDEX_IN_GEOMETRY:
5134             case TEST_TYPE_VIEW_INDEX_IN_TESELLATION:
5135                 groupViewIndex->addChild(groupShader.release());
5136                 break;
5137             default:
5138                 DE_ASSERT(0);
5139                 break;
5140             }
5141         }
5142 
5143         targetGroupPtr->addChild(groupViewIndex.release());
5144 
5145         if (renderPassType != RENDERING_TYPE_RENDERPASS_LEGACY)
5146             group->addChild(targetGroup.release());
5147     }
5148 }
5149 
5150 } // namespace MultiView
5151 } // namespace vkt
5152