1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2020 The Khronos Group Inc.
6  * Copyright (c) 2020 ARM Ltd.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21  * \file
22  * \brief VK_ARM_rasterization_order_attachment_access tests.
23  *//*--------------------------------------------------------------------*/
24 
25 #include "deDefs.hpp"
26 #include "deUniquePtr.hpp"
27 #include "tcuCommandLine.hpp"
28 #include "tcuImageCompare.hpp"
29 #include "tcuResource.hpp"
30 #include "tcuTestLog.hpp"
31 #include "tcuStringTemplate.hpp"
32 #include "vkBarrierUtil.hpp"
33 #include "vkBuilderUtil.hpp"
34 #include "vkCmdUtil.hpp"
35 #include "vkDefs.hpp"
36 #include "vkImageUtil.hpp"
37 #include "vkMemUtil.hpp"
38 #include "vkObjUtil.hpp"
39 #include "vkPlatform.hpp"
40 #include "vkPrograms.hpp"
41 #include "vkQueryUtil.hpp"
42 #include "vkRef.hpp"
43 #include "vkRefUtil.hpp"
44 #include "vktRasterizationOrderAttachmentAccessTests.hpp"
45 #include "vktRasterizationTests.hpp"
46 #include "vkTypeUtil.hpp"
47 #include "vktTestCase.hpp"
48 #include "vktTestCaseUtil.hpp"
49 #include "vktTestGroupUtil.hpp"
50 
51 using namespace vk;
52 using namespace std;
53 using namespace vkt;
54 using de::MovePtr;
55 
56 namespace vkt
57 {
58 
59 namespace rasterization
60 {
61 
62 namespace
63 {
64 
65 class AttachmentAccessOrderTestCase : public TestCase
66 {
67 public:
68     enum
69     {
70         ELEM_NUM = 6
71     };
72 
73     AttachmentAccessOrderTestCase(tcu::TestContext &context, const std::string &name, bool explicitSync,
74                                   bool overlapDraws, bool overlapPrimitives, bool overlapInstances,
75                                   VkSampleCountFlagBits sampleCount, uint32_t inputAttachmentNum, bool integerFormat);
76     virtual ~AttachmentAccessOrderTestCase(void);
77 
78     virtual void initPrograms(SourceCollections &programCollection) const;
79     virtual TestInstance *createInstance(Context &context) const;
80     virtual void checkSupport(Context &context) const;
81 
82     virtual uint32_t getInputAttachmentNum() const    = 0;
83     virtual uint32_t getColorAttachmentNum() const    = 0;
84     virtual bool hasDepthStencil() const              = 0;
85     virtual VkImageAspectFlagBits getDSAspect() const = 0;
86 
87     uint32_t m_inputAttachmentNum;
88     const bool m_explicitSync;
89     const bool m_overlapDraws;
90     const bool m_overlapPrimitives;
91     const bool m_overlapInstances;
92     VkSampleCountFlagBits m_sampleCount;
93     const uint32_t m_sampleNum;
94     const bool m_integerFormat;
95     static uint32_t getSampleNum(VkSampleCountFlagBits sampleCount);
96 
getColorFormat() const97     VkFormat getColorFormat() const
98     {
99         return m_integerFormat ? VK_FORMAT_R32G32_UINT : VK_FORMAT_R32G32_SFLOAT;
100     }
101 
102     VkFormat checkAndGetDSFormat(Context &context) const;
103 
getColorImageType()104     static VkImageType getColorImageType()
105     {
106         return VK_IMAGE_TYPE_2D;
107     }
108 
getColorImageTiling()109     static VkImageTiling getColorImageTiling()
110     {
111         return VK_IMAGE_TILING_OPTIMAL;
112     }
113 
getColorImageUsageFlags()114     static VkImageUsageFlags getColorImageUsageFlags()
115     {
116         return (VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
117                 VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
118     }
119 
getDSImageUsageFlags()120     static VkImageUsageFlags getDSImageUsageFlags()
121     {
122         return (VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT |
123                 VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
124     }
125 
getBlendStateFlags() const126     VkPipelineColorBlendStateCreateFlags getBlendStateFlags() const
127     {
128         return m_explicitSync ? 0 : VK_PIPELINE_COLOR_BLEND_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_BIT_ARM;
129     }
getDSStateFlags() const130     virtual VkPipelineDepthStencilStateCreateFlags getDSStateFlags() const
131     {
132         return 0;
133     }
hasDepth() const134     virtual bool hasDepth() const
135     {
136         return false;
137     }
hasStencil() const138     virtual bool hasStencil() const
139     {
140         return false;
141     }
142 
143 protected:
144     virtual void addShadersInternal(SourceCollections &programCollection,
145                                     const std::map<std::string, std::string> &params) const = 0;
146     void addSimpleVertexShader(SourceCollections &programCollection, const std::string &dest) const;
checkAdditionalRasterizationFlags(VkPhysicalDeviceRasterizationOrderAttachmentAccessFeaturesEXT & rasterizationAccess) const147     virtual void checkAdditionalRasterizationFlags(
148         VkPhysicalDeviceRasterizationOrderAttachmentAccessFeaturesEXT &rasterizationAccess) const
149     {
150         // unused parameter
151         DE_UNREF(rasterizationAccess);
152     }
153 };
154 
155 class AttachmentAccessOrderColorTestCase : public AttachmentAccessOrderTestCase
156 {
157 public:
AttachmentAccessOrderColorTestCase(tcu::TestContext & context,const std::string & name,bool explicitSync,bool overlapDraws,bool overlapPrimitives,bool overlapInstances,VkSampleCountFlagBits sampleCount,uint32_t inputAttachmentNum,bool integerFormat)158     AttachmentAccessOrderColorTestCase(tcu::TestContext &context, const std::string &name, bool explicitSync,
159                                        bool overlapDraws, bool overlapPrimitives, bool overlapInstances,
160                                        VkSampleCountFlagBits sampleCount, uint32_t inputAttachmentNum,
161                                        bool integerFormat)
162         : AttachmentAccessOrderTestCase(context, name, explicitSync, overlapDraws, overlapPrimitives, overlapInstances,
163                                         sampleCount, inputAttachmentNum, integerFormat)
164     {
165     }
166 
getInputAttachmentNum() const167     virtual uint32_t getInputAttachmentNum() const
168     {
169         return m_inputAttachmentNum;
170     }
171 
getColorAttachmentNum() const172     virtual uint32_t getColorAttachmentNum() const
173     {
174         return m_inputAttachmentNum;
175     }
176 
hasDepthStencil() const177     virtual bool hasDepthStencil() const
178     {
179         return false;
180     }
181 
getDSAspect() const182     virtual VkImageAspectFlagBits getDSAspect() const
183     {
184         /* not relevant, this return value will not be used */
185         return VK_IMAGE_ASPECT_FLAG_BITS_MAX_ENUM;
186     }
187 
188 protected:
189     virtual void addShadersInternal(SourceCollections &programCollection,
190                                     const std::map<std::string, std::string> &params) const;
191 };
192 
193 class AttachmentAccessOrderDepthTestCase : public AttachmentAccessOrderTestCase
194 {
195 public:
AttachmentAccessOrderDepthTestCase(tcu::TestContext & context,const std::string & name,bool explicitSync,bool overlapDraws,bool overlapPrimitives,bool overlapInstances,VkSampleCountFlagBits sampleCount)196     AttachmentAccessOrderDepthTestCase(tcu::TestContext &context, const std::string &name, bool explicitSync,
197                                        bool overlapDraws, bool overlapPrimitives, bool overlapInstances,
198                                        VkSampleCountFlagBits sampleCount)
199         : AttachmentAccessOrderTestCase(context, name, explicitSync, overlapDraws, overlapPrimitives, overlapInstances,
200                                         sampleCount, 1, false)
201     {
202     }
getInputAttachmentNum() const203     virtual uint32_t getInputAttachmentNum() const
204     {
205         return m_inputAttachmentNum + 1;
206     }
207 
getColorAttachmentNum() const208     virtual uint32_t getColorAttachmentNum() const
209     {
210         return m_inputAttachmentNum;
211     }
212 
hasDepth() const213     virtual bool hasDepth() const
214     {
215         return true;
216     }
hasDepthStencil() const217     virtual bool hasDepthStencil() const
218     {
219         return true;
220     }
221 
getDSAspect() const222     virtual VkImageAspectFlagBits getDSAspect() const
223     {
224         return VK_IMAGE_ASPECT_DEPTH_BIT;
225     }
getDSStateFlags() const226     virtual VkPipelineDepthStencilStateCreateFlags getDSStateFlags() const
227     {
228         return m_explicitSync ?
229                    0 :
230                    VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_DEPTH_ACCESS_BIT_ARM;
231     }
232 
233 protected:
234     virtual void addShadersInternal(SourceCollections &programCollection,
235                                     const std::map<std::string, std::string> &params) const;
checkAdditionalRasterizationFlags(VkPhysicalDeviceRasterizationOrderAttachmentAccessFeaturesEXT & rasterizationAccess) const236     virtual void checkAdditionalRasterizationFlags(
237         VkPhysicalDeviceRasterizationOrderAttachmentAccessFeaturesEXT &rasterizationAccess) const
238     {
239         if (!m_explicitSync && !rasterizationAccess.rasterizationOrderDepthAttachmentAccess)
240         {
241             TCU_THROW(NotSupportedError,
242                       "Implicit attachment access rasterization order not guaranteed for depth attachments");
243         }
244     }
245 };
246 
247 class AttachmentAccessOrderStencilTestCase : public AttachmentAccessOrderTestCase
248 {
249 public:
AttachmentAccessOrderStencilTestCase(tcu::TestContext & context,const std::string & name,bool explicitSync,bool overlapDraws,bool overlapPrimitives,bool overlapInstances,VkSampleCountFlagBits sampleCount)250     AttachmentAccessOrderStencilTestCase(tcu::TestContext &context, const std::string &name, bool explicitSync,
251                                          bool overlapDraws, bool overlapPrimitives, bool overlapInstances,
252                                          VkSampleCountFlagBits sampleCount)
253         : AttachmentAccessOrderTestCase(context, name, explicitSync, overlapDraws, overlapPrimitives, overlapInstances,
254                                         sampleCount, 1, true)
255     {
256     }
getInputAttachmentNum() const257     virtual uint32_t getInputAttachmentNum() const
258     {
259         return m_inputAttachmentNum + 1;
260     }
261 
getColorAttachmentNum() const262     virtual uint32_t getColorAttachmentNum() const
263     {
264         return m_inputAttachmentNum;
265     }
266 
hasStencil() const267     virtual bool hasStencil() const
268     {
269         return true;
270     }
hasDepthStencil() const271     virtual bool hasDepthStencil() const
272     {
273         return true;
274     }
275 
getDSAspect() const276     virtual VkImageAspectFlagBits getDSAspect() const
277     {
278         return VK_IMAGE_ASPECT_STENCIL_BIT;
279     }
getDSStateFlags() const280     virtual VkPipelineDepthStencilStateCreateFlags getDSStateFlags() const
281     {
282         return m_explicitSync ?
283                    0 :
284                    VK_PIPELINE_DEPTH_STENCIL_STATE_CREATE_RASTERIZATION_ORDER_ATTACHMENT_STENCIL_ACCESS_BIT_ARM;
285     }
286 
287 protected:
288     virtual void addShadersInternal(SourceCollections &programCollection,
289                                     const std::map<std::string, std::string> &params) const;
checkAdditionalRasterizationFlags(VkPhysicalDeviceRasterizationOrderAttachmentAccessFeaturesEXT & rasterizationAccess) const290     virtual void checkAdditionalRasterizationFlags(
291         VkPhysicalDeviceRasterizationOrderAttachmentAccessFeaturesEXT &rasterizationAccess) const
292     {
293         if (!m_explicitSync && !rasterizationAccess.rasterizationOrderStencilAttachmentAccess)
294         {
295             TCU_THROW(NotSupportedError,
296                       "Implicit attachment access rasterization order not guaranteed for stencil attachments");
297         }
298     }
299 };
300 
301 class AttachmentAccessOrderTestInstance : public TestInstance
302 {
303 public:
304     AttachmentAccessOrderTestInstance(Context &context, const AttachmentAccessOrderTestCase *testCase);
305     virtual ~AttachmentAccessOrderTestInstance(void);
306     virtual tcu::TestStatus iterate(void);
307 
308 protected:
309     class RenderSubpass
310     {
311     public:
312         const AttachmentAccessOrderTestCase *m_testCase;
313         uint32_t m_subpass;
314         VkSampleCountFlagBits m_sampleCount;
315         Move<VkPipeline> m_pipeline;
316         Move<VkPipelineLayout> m_pipelineLayout;
317         uint32_t m_colorAttNum;
318         std::vector<Move<VkImage>> m_inputAtt;
319         std::vector<MovePtr<Allocation>> m_inputAttMemory;
320         std::vector<Move<VkImageView>> m_inputAttView;
321         std::vector<VkAttachmentReference> m_attachmentReferences;
322 
323         void createAttachments(int subpass, uint32_t inputAttachmentNum, uint32_t colorAttachmentNum,
324                                VkSampleCountFlagBits sampleCount, Context &context, vector<VkImageView> &views,
325                                VkDescriptorSetLayout *pDsetLayout, const AttachmentAccessOrderTestCase *tc);
326         void createPipeline(VkRenderPass renderPass, Context &context);
327 
getColorAttachmentNum()328         uint32_t getColorAttachmentNum()
329         {
330             return m_colorAttNum;
331         }
getInputAttachmentNum()332         uint32_t getInputAttachmentNum()
333         {
334             return static_cast<uint32_t>(m_inputAtt.size());
335         }
getDepthStencilAttachment()336         VkAttachmentReference *getDepthStencilAttachment()
337         {
338             return (getColorAttachmentNum() == getInputAttachmentNum()) ? DE_NULL :
339                                                                           &m_attachmentReferences[m_colorAttNum];
340         }
341     };
342     void addPipelineBarrier(VkCommandBuffer cmdBuffer, VkImage image, VkImageLayout oldLayout, VkImageLayout newLayout,
343                             VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkPipelineStageFlags srcStageMask,
344                             VkPipelineStageFlags dstStageMask, VkImageAspectFlags aspect = VK_IMAGE_ASPECT_COLOR_BIT);
345 
346     void addClearColor(VkCommandBuffer cmdBuffer, VkImage image);
347     void addClearDepthStencil(VkCommandBuffer cmdBuffer, VkImage image);
348 
349     void writeDescriptorSets();
350     Move<VkRenderPass> createRenderPass(VkFormat attFormat);
351     void createVertexBuffer();
352     void createResultBuffer();
353     void addDependency(vector<VkSubpassDependency> &dependencies, uint32_t source, uint32_t dst,
354                        VkPipelineStageFlags pipelineFlags, VkAccessFlags accessFlags);
355 
356     tcu::TestStatus validateResults(uint32_t numDraws, uint32_t numPrimitives, uint32_t numInstances);
357 
358     const AttachmentAccessOrderTestCase *m_testCase;
359 
360     const DeviceInterface &m_vk;
361     vector<RenderSubpass> m_subpasses;
362     Move<VkRenderPass> m_renderPass;
363     Move<VkFramebuffer> m_framebuffer;
364     Move<VkBuffer> m_vertexBuffer;
365     MovePtr<Allocation> m_vertexBufferMemory;
366     Move<VkCommandPool> m_cmdPool;
367     Move<VkCommandBuffer> m_cmdBuffer;
368     Move<VkSampler> m_sampler;
369     Move<VkDescriptorSetLayout> m_descSetLayout;
370     Move<VkDescriptorPool> m_descPool;
371     Move<VkDescriptorSet> m_descSet;
372 
373     Move<VkBuffer> m_resultBuffer;
374     MovePtr<Allocation> m_resultBufferMemory;
375 
376     enum
377     {
378         WIDTH  = 8,
379         HEIGHT = 8,
380     };
381 };
382 
AttachmentAccessOrderTestCase(tcu::TestContext & context,const std::string & name,bool explicitSync,bool overlapDraws,bool overlapPrimitives,bool overlapInstances,VkSampleCountFlagBits sampleCount,uint32_t inputAttachmentNum,bool integerFormat)383 AttachmentAccessOrderTestCase::AttachmentAccessOrderTestCase(tcu::TestContext &context, const std::string &name,
384                                                              bool explicitSync, bool overlapDraws,
385                                                              bool overlapPrimitives, bool overlapInstances,
386                                                              VkSampleCountFlagBits sampleCount,
387                                                              uint32_t inputAttachmentNum, bool integerFormat)
388     : TestCase(context, name)
389     , m_inputAttachmentNum(inputAttachmentNum)
390     , m_explicitSync(explicitSync)
391     , m_overlapDraws(overlapDraws)
392     , m_overlapPrimitives(overlapPrimitives)
393     , m_overlapInstances(overlapInstances)
394     , m_sampleCount(sampleCount)
395     , m_sampleNum(getSampleNum(sampleCount))
396     , m_integerFormat(integerFormat)
397 {
398 }
399 
~AttachmentAccessOrderTestCase(void)400 AttachmentAccessOrderTestCase::~AttachmentAccessOrderTestCase(void)
401 {
402 }
addSimpleVertexShader(SourceCollections & programCollection,const std::string & dest) const403 void AttachmentAccessOrderTestCase::addSimpleVertexShader(SourceCollections &programCollection,
404                                                           const std::string &dest) const
405 {
406     /*
407      * The "prim_id" variable here (and in other tests below) is emulating gl_PrimitiveID.
408      * This is done to avoid having this test dependon the geometry shader feature.
409      * Note that this emulation only works because the draw calls used in the tests are
410      * non-indexed independent triangles.
411      */
412     std::stringstream vertShader;
413     vertShader << "#version 310 es\n"
414                << "layout(location = 0) in highp vec2 v_position;\n"
415                << "layout(location = 1) flat out int prim_id;\n"
416                << "void main ()\n"
417                << "{\n"
418                << "    prim_id = gl_VertexIndex / 3;\n"
419                << "    gl_Position = vec4(v_position, float(gl_InstanceIndex)/256.0, 1);\n"
420                << "}\n";
421 
422     programCollection.glslSources.add(dest) << glu::VertexSource(vertShader.str());
423 }
424 
addShadersInternal(SourceCollections & programCollection,const std::map<std::string,std::string> & params) const425 void AttachmentAccessOrderColorTestCase::addShadersInternal(SourceCollections &programCollection,
426                                                             const std::map<std::string, std::string> &params) const
427 {
428     addSimpleVertexShader(programCollection, "vert1");
429     addSimpleVertexShader(programCollection, "vert2");
430 
431     std::stringstream fragShader;
432     fragShader << "#version 450\n"
433                << "precision highp ${SCALAR_NAME};\n"
434                << "precision highp ${SUBPASS_INPUT};\n";
435     for (uint32_t i = 0; i < m_inputAttachmentNum; i++)
436     {
437         fragShader << "layout( set = 0, binding = " << i << ", input_attachment_index = " << i
438                    << " ) uniform ${SUBPASS_INPUT} in" << i << ";\n"
439                    << "layout( location = " << i << " ) out ${VEC_NAME}2 out" << i << ";\n";
440     }
441 
442     fragShader
443         << "layout( push_constant ) uniform ConstBlock\n"
444         << "{\n"
445         << "    uint drawCur;\n"
446         << "};\n"
447         << "layout(location = 1) flat in int prim_id;\n"
448         << "void main()\n"
449         << "{\n"
450         << "    uint instanceCur = uint(round(gl_FragCoord.z * 256.0));\n"
451         << "    uint primitiveCur = uint(prim_id) / 2u;\n"
452         << "    uint primitiveNum = ${PRIMITIVE_NUM}u;\n"
453         << "    uint instanceNum = ${INSTANCE_NUM}u;\n"
454         << "    uint drawNum = ${DRAW_NUM}u;\n"
455         << "    uint curIndex = drawCur * instanceNum * primitiveNum + instanceCur * primitiveNum + primitiveCur;\n"
456         << "    uint total = drawNum * instanceNum * primitiveNum;\n"
457         << "    uint zero = curIndex / total;\n"
458         << "    uint index;\n"
459         << "    uint pre_fetch_loop = uint(gl_FragCoord.x) * uint(gl_FragCoord.y) * (drawNum * primitiveNum - "
460            "drawCur * primitiveNum - primitiveCur);\n"
461         << "    uint post_fetch_loop = uint(gl_FragCoord.x) + uint(gl_FragCoord.y) + (drawNum * instanceNum - "
462            "drawCur * instanceNum - instanceCur);\n"
463         << "    for(index = 0u; index < pre_fetch_loop; index++)\n"
464         << "    {\n"
465         << "        zero = uint(sin(float(zero)));\n"
466         << "    }\n"
467         << "    ${VEC_NAME}2 previous[${ATT_NUM}];\n";
468 
469     for (uint32_t i = 0; i < m_inputAttachmentNum; i++)
470     {
471         if (m_sampleCount == VK_SAMPLE_COUNT_1_BIT)
472         {
473             fragShader << "    previous[" << i << "] = subpassLoad( in" << i << ").xy;\n";
474         }
475         else
476         {
477             fragShader << "    previous[" << i << "] = subpassLoad( in" << i << ", gl_SampleID).xy;\n";
478         }
479     }
480     fragShader << "    for(index = 0u; index < post_fetch_loop; index++)\n"
481                << "    {\n"
482                << "        zero = uint(sin(float(zero)));\n"
483                << "    }\n";
484     for (uint32_t i = 0; i < m_inputAttachmentNum; i++)
485     {
486         fragShader << "    if (previous[" << i << "].y == 0 && curIndex == 0)\n"
487                    << "    {\n"
488                    << "        out" << i << ".y = previous[" << i << "].y + (1u + zero + gl_SampleID + " << i << "u);\n"
489                    << "        out" << i << ".x = previous[" << i << "].x;\n"
490                    << "    }\n"
491                    << "    else if (previous[" << i << "].y == curIndex + gl_SampleID + " << i << ")\n"
492                    << "    {\n"
493                    << "        out" << i << ".y = previous[" << i << "].y + 1 + zero;\n"
494                    << "        out" << i << ".x = previous[" << i << "].x;\n"
495                    << "    }\n"
496                    << "    else\n"
497                    << "    {\n"
498                    << "        out" << i << ".y = 0u;\n"
499                    << "        out" << i << ".x = 1u;\n"
500                    << "    }\n";
501     }
502     fragShader << "}\n";
503 
504     tcu::StringTemplate fragShaderTpl(fragShader.str());
505 
506     programCollection.glslSources.add("frag") << glu::FragmentSource(fragShaderTpl.specialize(params));
507 }
addShadersInternal(SourceCollections & programCollection,const std::map<std::string,std::string> & params) const508 void AttachmentAccessOrderDepthTestCase::addShadersInternal(SourceCollections &programCollection,
509                                                             const std::map<std::string, std::string> &params) const
510 {
511     std::stringstream vertShader;
512     vertShader << "#version 460\n"
513                << "layout(location = 0) in highp vec2 v_position;\n"
514                << "layout(location = 1) flat out uint instance_index;\n"
515                << "layout(location = 2) flat out int prim_id;\n"
516                << "layout( push_constant ) uniform ConstBlock\n"
517                << "{\n"
518                << "    uint drawCur;\n"
519                << "};\n"
520                << "void main ()\n"
521                << "{\n"
522                << "    uint primitiveCur = uint(gl_VertexIndex) / 6u;\n"
523                << "    prim_id = gl_VertexIndex / 3;\n"
524                << "    uint instanceNum = ${INSTANCE_NUM};\n"
525                << "    uint primitiveNum = ${PRIMITIVE_NUM};\n"
526                << "    uint drawNum = ${DRAW_NUM};\n"
527                << "    uint curIndex = drawCur * instanceNum * primitiveNum + gl_InstanceIndex * primitiveNum + "
528                   "primitiveCur;\n"
529                << "    uint indexNum = drawNum * instanceNum * primitiveNum;\n"
530                << "    instance_index = gl_InstanceIndex;\n"
531                << "    gl_Position = vec4(v_position, 0.125 * float(curIndex) / float(indexNum), 1);\n"
532                << "}\n";
533 
534     tcu::StringTemplate vertShaderTpl(vertShader.str());
535     programCollection.glslSources.add("vert1") << glu::VertexSource(vertShaderTpl.specialize(params));
536     addSimpleVertexShader(programCollection, "vert2");
537 
538     std::stringstream fragShader;
539     fragShader
540         << "#version 450\n"
541         << "precision highp ${SCALAR_NAME};\n"
542         << "precision highp ${SUBPASS_INPUT};\n"
543         << "layout( set = 0, binding = 0, input_attachment_index = 0 ) uniform ${SUBPASS_INPUT} in_color;\n"
544         << "layout( set = 0, binding = 1, input_attachment_index = 1 ) uniform ${SUBPASS_INPUT} in_ds;\n"
545         << "layout( location = 0 ) out ${VEC_NAME}2 out0;\n"
546         << "layout( location = 1 ) flat in uint instance_index;\n"
547         << "layout( location = 2 ) flat in int prim_id;\n"
548         << "layout( push_constant ) uniform ConstBlock\n"
549         << "{\n"
550         << "    uint drawCur;\n"
551         << "};\n"
552         << "void main()\n"
553         << "{\n"
554         << "    uint instanceCur = instance_index;\n"
555         << "    uint primitiveCur = uint(prim_id) / 2u;\n"
556         << "    uint primitiveNum = ${PRIMITIVE_NUM}u;\n"
557         << "    uint instanceNum = ${INSTANCE_NUM}u;\n"
558         << "    uint drawNum = ${DRAW_NUM}u;\n"
559         << "    uint curIndex = drawCur * instanceNum * primitiveNum + instanceCur * primitiveNum + primitiveCur;\n"
560         << "    uint total = drawNum * instanceNum * primitiveNum;\n"
561         << "    uint zero = curIndex / total;\n"
562         << "    uint index;\n"
563         << "    uint pre_fetch_loop = uint(gl_FragCoord.x) * uint(gl_FragCoord.y) * (drawNum * primitiveNum - "
564            "drawCur * primitiveNum - primitiveCur);\n"
565         << "    uint post_fetch_loop = uint(gl_FragCoord.x) + uint(gl_FragCoord.y) + (drawNum * instanceNum - "
566            "drawCur * instanceNum - instanceCur);\n"
567         << "    for(index = 0u; index < pre_fetch_loop; index++)\n"
568         << "    {\n"
569         << "        zero = uint(sin(float(zero)));\n"
570         << "    }\n";
571     if (m_sampleCount == VK_SAMPLE_COUNT_1_BIT)
572     {
573         fragShader << "    vec2 ds = subpassLoad( in_ds ).xy;\n"
574                    << "    ${VEC_NAME}2 color = subpassLoad( in_color ).xy;\n";
575     }
576     else
577     {
578         fragShader << "    vec2 ds = subpassLoad( in_ds, gl_SampleID ).xy;\n"
579                    << "    ${VEC_NAME}2 color = subpassLoad( in_color, gl_SampleID ).xy;\n";
580     }
581     fragShader << "    for(index = 0u; index < post_fetch_loop; index++)\n"
582                << "    {\n"
583                << "        zero = uint(sin(float(zero)));\n"
584                << "    }\n"
585                << "    if (curIndex == 0 && ds.x == 0)\n"
586                << "    {\n"
587                << "        out0.x = color.x;\n"
588                << "        out0.y = curIndex + 1 + gl_SampleID + zero;\n";
589     if (m_sampleCount != VK_SAMPLE_COUNT_1_BIT)
590     {
591         fragShader << "        gl_FragDepth = 0.125 * (float(curIndex) / float(total)) + gl_SampleID / 128.0;\n";
592     }
593     fragShader << "    }\n"
594                << "    else\n"
595                << "    {\n"
596                << "        const float expected = 0.125 * float(curIndex - 1) / float(total) + gl_SampleID / 128.0;\n"
597                << "        const float threshold = 0.0000001;\n"
598                << "        if (ds.x >= expected - threshold && ds.x <= expected + threshold)\n"
599                << "        {\n"
600                << "            out0.x = color.x;\n"
601                << "            out0.y = curIndex + 1 + gl_SampleID + zero;\n";
602     if (m_sampleCount != VK_SAMPLE_COUNT_1_BIT)
603     {
604         fragShader << "            gl_FragDepth = 0.125 * (float(curIndex) / float(total)) + gl_SampleID / 128.0;\n";
605     }
606     fragShader << "        }\n"
607                << "        else\n"
608                << "        {\n"
609                << "            out0.y = 0;\n"
610                << "            out0.x = 1u;\n"
611                << "        }\n"
612                << "    }\n"
613                << "}\n";
614 
615     tcu::StringTemplate fragShaderTpl(fragShader.str());
616 
617     programCollection.glslSources.add("frag") << glu::FragmentSource(fragShaderTpl.specialize(params));
618 }
addShadersInternal(SourceCollections & programCollection,const std::map<std::string,std::string> & params) const619 void AttachmentAccessOrderStencilTestCase::addShadersInternal(SourceCollections &programCollection,
620                                                               const std::map<std::string, std::string> &params) const
621 {
622     std::stringstream vertShader;
623     vertShader << "#version 460\n"
624                << "layout(location = 0) in highp vec2 v_position;\n"
625                << "layout(location = 1) flat out uint instance_index;"
626                << "layout(location = 2) flat out int prim_id;\n"
627                << "layout( push_constant ) uniform ConstBlock\n"
628                << "{\n"
629                << "    uint drawCur;\n"
630                << "};\n"
631                << "void main ()\n"
632                << "{\n"
633                << "    uint primitiveCur = uint(gl_VertexIndex) / 6u;\n"
634                << "    prim_id = gl_VertexIndex / 3;\n"
635                << "    uint instanceNum = ${INSTANCE_NUM};\n"
636                << "    uint primitiveNum = ${PRIMITIVE_NUM};\n"
637                << "    uint drawNum = ${DRAW_NUM};\n"
638                << "    uint curIndex = drawCur * instanceNum * primitiveNum + gl_InstanceIndex * primitiveNum + "
639                   "primitiveCur;\n"
640                << "    uint indexNum = drawNum * instanceNum * primitiveNum;\n"
641                << "    instance_index = gl_InstanceIndex;\n"
642                << "    gl_Position = vec4(v_position, 0.125 * float(curIndex) / float(indexNum), 1);\n"
643                << "}\n";
644 
645     tcu::StringTemplate vertShaderTpl(vertShader.str());
646     programCollection.glslSources.add("vert1") << glu::VertexSource(vertShaderTpl.specialize(params));
647     addSimpleVertexShader(programCollection, "vert2");
648 
649     std::stringstream fragShader;
650     fragShader
651         << "#version 450\n"
652         << "precision highp ${SCALAR_NAME};\n"
653         << "precision highp ${SUBPASS_INPUT};\n"
654         << "layout( set = 0, binding = 0, input_attachment_index = 0 ) uniform ${SUBPASS_INPUT} in_color;\n"
655         << "layout( set = 0, binding = 1, input_attachment_index = 1 ) uniform ${SUBPASS_INPUT} in_ds;\n"
656         << "layout( location = 0 ) out ${VEC_NAME}2 out0;\n"
657         << "layout( location = 1 ) flat in uint instance_index;\n"
658         << "layout( location = 2 ) flat in int prim_id;\n"
659         << "layout( push_constant ) uniform ConstBlock\n"
660         << "{\n"
661         << "    uint drawCur;\n"
662         << "};\n"
663         << "void main()\n"
664         << "{\n"
665         << "    uint instanceCur = instance_index;\n"
666         << "    uint primitiveCur = uint(prim_id) / 2u;\n"
667         << "    uint primitiveNum = ${PRIMITIVE_NUM}u;\n"
668         << "    uint instanceNum = ${INSTANCE_NUM}u;\n"
669         << "    uint drawNum = ${DRAW_NUM}u;\n"
670         << "    uint curIndex = drawCur * instanceNum * primitiveNum + instanceCur * primitiveNum + primitiveCur;\n"
671         << "    uint total = drawNum * instanceNum * primitiveNum;\n"
672         << "    uint zero = curIndex / total;\n"
673         << "    uint index;\n"
674         << "    uint pre_fetch_loop = uint(gl_FragCoord.x) * uint(gl_FragCoord.y) * (drawNum * primitiveNum - "
675            "drawCur * primitiveNum - primitiveCur);\n"
676         << "    uint post_fetch_loop = uint(gl_FragCoord.x) + uint(gl_FragCoord.y) + (drawNum * instanceNum - "
677            "drawCur * instanceNum - instanceCur);\n"
678         << "    for(index = 0u; index < pre_fetch_loop; index++)\n"
679         << "    {\n"
680         << "        zero = uint(sin(float(zero)));\n"
681         << "    }\n";
682     if (m_sampleCount == VK_SAMPLE_COUNT_1_BIT)
683     {
684         fragShader << "    ${VEC_NAME}2 ds = subpassLoad( in_ds ).xy;\n"
685                    << "    ${VEC_NAME}2 color = subpassLoad( in_color ).xy;\n";
686     }
687     else
688     {
689         fragShader << "    ${VEC_NAME}2 ds = subpassLoad( in_ds, gl_SampleID).xy;\n"
690                    << "    ${VEC_NAME}2 color = subpassLoad( in_color, gl_SampleID).xy;\n";
691     }
692     fragShader << "    for(index = 0u; index < post_fetch_loop; index++)\n"
693                << "    {\n"
694                << "        zero = uint(sin(float(zero)));\n"
695                << "    }\n"
696                << "    if (ds.x == curIndex)\n"
697                << "    {\n"
698                << "        out0.x = color.x;\n"
699                << "        out0.y = curIndex + 1 + gl_SampleID + zero;\n"
700                << "    }\n"
701                << "    else\n"
702                << "    {\n"
703                << "        out0.y = 0;\n"
704                << "        out0.x = 1u;\n"
705                << "    }\n"
706                << "}\n";
707 
708     tcu::StringTemplate fragShaderTpl(fragShader.str());
709 
710     programCollection.glslSources.add("frag") << glu::FragmentSource(fragShaderTpl.specialize(params));
711 }
712 
initPrograms(SourceCollections & programCollection) const713 void AttachmentAccessOrderTestCase::initPrograms(SourceCollections &programCollection) const
714 {
715     std::map<std::string, std::string> params;
716 
717     params["PRIMITIVE_NUM"] = std::to_string(m_overlapPrimitives ? ELEM_NUM : 1);
718     params["INSTANCE_NUM"]  = std::to_string(m_overlapInstances ? ELEM_NUM : 1);
719     params["DRAW_NUM"]      = std::to_string(m_overlapDraws ? ELEM_NUM : 1);
720     params["ATT_NUM"]       = std::to_string(m_inputAttachmentNum);
721     params["SAMPLE_NUM"]    = std::to_string(m_sampleNum);
722 
723     if (m_integerFormat)
724     {
725         params["SUBPASS_INPUT"] = "usubpassInput";
726         params["SCALAR_NAME"]   = "int";
727         params["VEC_NAME"]      = "uvec";
728     }
729     else
730     {
731         params["SUBPASS_INPUT"] = "subpassInput";
732         params["SCALAR_NAME"]   = "float";
733         params["VEC_NAME"]      = "vec";
734     }
735     if (m_sampleCount != VK_SAMPLE_COUNT_1_BIT)
736     {
737         params["SUBPASS_INPUT"] = params["SUBPASS_INPUT"] + "MS";
738     }
739 
740     /* add the vertex (for both renderpasses) and fragment shaders for first renderpass */
741     addShadersInternal(programCollection, params);
742 
743     std::stringstream fragShaderResolve;
744     fragShaderResolve << "#version 450\n"
745                       << "precision highp ${SCALAR_NAME};\n"
746                       << "precision highp ${SUBPASS_INPUT};\n";
747     for (uint32_t i = 0; i < m_inputAttachmentNum; i++)
748     {
749         fragShaderResolve << "layout( set = 0, binding = " << i << ", input_attachment_index = " << i
750                           << " ) uniform ${SUBPASS_INPUT} in" << i << ";\n";
751     }
752     fragShaderResolve << "layout( location = 0 ) out ${VEC_NAME}2 out0;\n";
753 
754     fragShaderResolve << "void main()\n"
755                       << "{\n"
756                       << "    uint primitiveNum = ${PRIMITIVE_NUM}u;\n"
757                       << "    uint instanceNum = ${INSTANCE_NUM}u;\n"
758                       << "    uint drawNum = ${DRAW_NUM}u;\n"
759                       << "    uint sampleNum = ${SAMPLE_NUM}u;\n"
760                       << "    uint totalNum = primitiveNum * instanceNum * drawNum;\n"
761                       << "    out0.y = totalNum;\n"
762                       << "    out0.x = 0u;\n"
763                       << "    ${VEC_NAME}2 val;\n"
764                       << "    int i;\n";
765 
766     for (uint32_t i = 0; i < m_inputAttachmentNum; i++)
767     {
768         if (m_sampleNum == 1)
769         {
770             fragShaderResolve << "    val = subpassLoad(in" << i << ").xy;\n"
771                               << "    if (val.x != 0u || val.y != totalNum + " << i << "){\n"
772                               << "        out0.y = val.y;\n"
773                               << "        out0.x = val.x;\n"
774                               << "    }\n";
775         }
776         else
777         {
778             fragShaderResolve << "    for (i = 0; i < sampleNum; i++) {\n"
779                               << "        val = subpassLoad(in" << i << ", i).xy;\n"
780                               << "        if (val.x != 0u || val.y != totalNum + i + " << i << "){\n"
781                               << "            out0.y = val.y;\n"
782                               << "            out0.x = val.x;\n"
783                               << "        }\n"
784                               << "    }\n";
785         }
786     }
787 
788     fragShaderResolve << "}\n";
789 
790     tcu::StringTemplate fragShaderResolveTpl(fragShaderResolve.str());
791 
792     programCollection.glslSources.add("frag_resolve") << glu::FragmentSource(fragShaderResolveTpl.specialize(params));
793 }
794 
createInstance(Context & context) const795 TestInstance *AttachmentAccessOrderTestCase::createInstance(Context &context) const
796 {
797     return new AttachmentAccessOrderTestInstance(context, this);
798 }
799 
checkAndGetDSFormat(Context & context) const800 VkFormat AttachmentAccessOrderTestCase::checkAndGetDSFormat(Context &context) const
801 {
802     const auto &vki           = context.getInstanceInterface();
803     const auto physicalDevice = context.getPhysicalDevice();
804     const auto imageType      = getColorImageType();
805     const auto imageTiling    = getColorImageTiling();
806     const auto imageUsage     = getDSImageUsageFlags();
807 
808     const std::vector<VkFormat> dsFormats{VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT};
809     VkFormat supportedFormat = VK_FORMAT_UNDEFINED;
810     VkImageFormatProperties formatProperties;
811 
812     for (const auto &dsFormat : dsFormats)
813     {
814         const auto result = vki.getPhysicalDeviceImageFormatProperties(physicalDevice, dsFormat, imageType, imageTiling,
815                                                                        imageUsage, 0u, &formatProperties);
816 
817         if (result == VK_SUCCESS)
818         {
819             if ((formatProperties.sampleCounts & m_sampleCount) != 0)
820             {
821                 supportedFormat = dsFormat;
822                 break;
823             }
824         }
825         else if (result != VK_ERROR_FORMAT_NOT_SUPPORTED)
826             TCU_FAIL("vkGetPhysicalDeviceImageFormatProperties returned unexpected error");
827     }
828 
829     return supportedFormat;
830 }
831 
checkSupport(Context & context) const832 void AttachmentAccessOrderTestCase::checkSupport(Context &context) const
833 {
834     context.requireInstanceFunctionality("VK_KHR_get_physical_device_properties2");
835 
836     // When explicit synchronization is used, there's no need for the extension.
837     if (!m_explicitSync)
838         if (!context.isDeviceFunctionalitySupported("VK_ARM_rasterization_order_attachment_access") &&
839             !context.isDeviceFunctionalitySupported("VK_EXT_rasterization_order_attachment_access"))
840             TCU_THROW(NotSupportedError, "Neither VK_ARM_rasterization_order_attachment_access nor "
841                                          "VK_EXT_rasterization_order_attachment_access is supported");
842 
843     const auto &vki           = context.getInstanceInterface();
844     const auto physicalDevice = context.getPhysicalDevice();
845 
846     VkPhysicalDeviceRasterizationOrderAttachmentAccessFeaturesEXT rasterizationAccess = initVulkanStructure();
847     VkPhysicalDeviceFeatures2 features2 = initVulkanStructure(m_explicitSync ? nullptr : &rasterizationAccess);
848 
849     vki.getPhysicalDeviceFeatures2(physicalDevice, &features2);
850 
851     VkPhysicalDeviceProperties2 properties2 = initVulkanStructure();
852 
853     vki.getPhysicalDeviceProperties2(physicalDevice, &properties2);
854 
855     if (m_integerFormat)
856     {
857         const auto format      = getColorFormat();
858         const auto imageType   = getColorImageType();
859         const auto imageTiling = getColorImageTiling();
860         const auto imageUsage  = getColorImageUsageFlags();
861 
862         VkImageFormatProperties formatProperties;
863 
864         const auto result = vki.getPhysicalDeviceImageFormatProperties(physicalDevice, format, imageType, imageTiling,
865                                                                        imageUsage, 0u, &formatProperties);
866         if (result != VK_SUCCESS)
867         {
868             if (result == VK_ERROR_FORMAT_NOT_SUPPORTED)
869                 TCU_THROW(NotSupportedError,
870                           "format " + de::toString(format) + " does not support the required features");
871             else
872                 TCU_FAIL("vkGetPhysicalDeviceImageFormatProperties returned unexpected error");
873         }
874 
875         if ((formatProperties.sampleCounts & m_sampleCount) == 0 ||
876             (properties2.properties.limits.sampledImageIntegerSampleCounts & m_sampleCount) == 0)
877         {
878             TCU_THROW(NotSupportedError, "Sample count not supported");
879         }
880     }
881     else
882     {
883         if ((properties2.properties.limits.framebufferColorSampleCounts & m_sampleCount) == 0 ||
884             (properties2.properties.limits.sampledImageColorSampleCounts & m_sampleCount) == 0)
885         {
886             TCU_THROW(NotSupportedError, "Sample count not supported");
887         }
888     }
889 
890     // Check depth/stencil format support if needed.
891     if (getInputAttachmentNum() > getColorAttachmentNum())
892     {
893         const auto format = checkAndGetDSFormat(context);
894         if (format == VK_FORMAT_UNDEFINED)
895             TCU_THROW(NotSupportedError, "No support for any of the required depth/stencil formats");
896     }
897 
898     /* sampleRateShading must be enabled to call fragment shader for all the samples in multisampling */
899     if (m_sampleCount != VK_SAMPLE_COUNT_1_BIT && !features2.features.sampleRateShading)
900     {
901         TCU_THROW(NotSupportedError, "sampleRateShading feature not supported");
902     }
903 
904     if (properties2.properties.limits.maxFragmentOutputAttachments < m_inputAttachmentNum ||
905         properties2.properties.limits.maxPerStageDescriptorInputAttachments < m_inputAttachmentNum)
906     {
907         TCU_THROW(NotSupportedError, "Feedback attachment number not supported");
908     }
909 
910     if (!m_explicitSync && !rasterizationAccess.rasterizationOrderColorAttachmentAccess)
911     {
912         TCU_THROW(NotSupportedError,
913                   "Implicit attachment access rasterization order not guaranteed for color attachments");
914     }
915 
916     checkAdditionalRasterizationFlags(rasterizationAccess);
917 }
918 
getSampleNum(VkSampleCountFlagBits sampleCount)919 uint32_t AttachmentAccessOrderTestCase::getSampleNum(VkSampleCountFlagBits sampleCount)
920 {
921     uint32_t ret = 0;
922     switch (sampleCount)
923     {
924     case VK_SAMPLE_COUNT_1_BIT:
925         ret = 1;
926         break;
927     case VK_SAMPLE_COUNT_2_BIT:
928         ret = 2;
929         break;
930     case VK_SAMPLE_COUNT_4_BIT:
931         ret = 4;
932         break;
933     case VK_SAMPLE_COUNT_8_BIT:
934         ret = 8;
935         break;
936     case VK_SAMPLE_COUNT_16_BIT:
937         ret = 16;
938         break;
939     case VK_SAMPLE_COUNT_32_BIT:
940         ret = 32;
941         break;
942     case VK_SAMPLE_COUNT_64_BIT:
943         ret = 64;
944         break;
945     default:
946         DE_ASSERT(false);
947     };
948     return ret;
949 }
950 
createAttachments(int subpass,uint32_t inputAttachmentNum,uint32_t colorAttachmentNum,VkSampleCountFlagBits sampleCount,Context & context,vector<VkImageView> & views,VkDescriptorSetLayout * pDsetLayout,const AttachmentAccessOrderTestCase * tc)951 void AttachmentAccessOrderTestInstance::RenderSubpass::createAttachments(int subpass, uint32_t inputAttachmentNum,
952                                                                          uint32_t colorAttachmentNum,
953                                                                          VkSampleCountFlagBits sampleCount,
954                                                                          Context &context, vector<VkImageView> &views,
955                                                                          VkDescriptorSetLayout *pDsetLayout,
956                                                                          const AttachmentAccessOrderTestCase *tc)
957 {
958     m_testCase                      = tc;
959     m_subpass                       = subpass;
960     m_sampleCount                   = sampleCount;
961     m_colorAttNum                   = colorAttachmentNum;
962     const DeviceInterface &vk       = context.getDeviceInterface();
963     const VkDevice device           = context.getDevice();
964     const uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
965     Allocator &allocator            = context.getDefaultAllocator();
966 
967     // Pipeline Layout
968     {
969         VkPushConstantRange pushConstantsInfo = {
970             VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlags stageFlags;
971             0,                            // uint32_t offset;
972             4,                            // uint32_t size;
973         };
974         if (m_testCase->hasDepthStencil())
975         {
976             pushConstantsInfo.stageFlags |= VK_SHADER_STAGE_VERTEX_BIT;
977         }
978         const VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = {
979             VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
980             DE_NULL,                                       // const void* pNext;
981             0u,                                            // VkPipelineLayoutCreateFlags flags;
982             1u,                                            // uint32_t descriptorSetCount;
983             pDsetLayout,                                   // const VkDescriptorSetLayout* pSetLayouts;
984             m_subpass == 0 ? 1u : 0u,                      // uint32_t pushConstantRangeCount;
985             m_subpass == 0 ? &pushConstantsInfo : nullptr  // const VkPushConstantRange* pPushConstantRanges;
986         };
987         m_pipelineLayout = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
988     }
989     VkFormat attFormat = m_testCase->getColorFormat();
990 
991     /* Same create info for all the color attachments */
992     const auto imageType   = AttachmentAccessOrderTestCase::getColorImageType();
993     const auto imageTiling = AttachmentAccessOrderTestCase::getColorImageTiling();
994     const auto imageUsage  = AttachmentAccessOrderTestCase::getColorImageUsageFlags();
995 
996     VkImageCreateInfo colorImageCreateInfo = {
997         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
998         DE_NULL,                             // const void* pNext;
999         0u,                                  // VkImageCreateFlags flags;
1000         imageType,                           // VkImageType imageType;
1001         attFormat,                           // VkFormat format;
1002         {WIDTH, HEIGHT, 1u},                 // VkExtent3D extent;
1003         1u,                                  // uint32_t mipLevels;
1004         1u,                                  // uint32_t arrayLayers;
1005         sampleCount,                         // VkSampleCountFlagBits samples;
1006         imageTiling,                         // VkImageTiling tiling;
1007         imageUsage,                          // VkImageUsageFlags usage;
1008         VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode sharingMode;
1009         1u,                                  // uint32_t queueFamilyIndexCount;
1010         &queueFamilyIndex,                   // const uint32_t* pQueueFamilyIndices;
1011         VK_IMAGE_LAYOUT_UNDEFINED            // VkImageLayout initialLayout;
1012     };
1013 
1014     for (uint32_t i = 0; i < inputAttachmentNum; i++)
1015     {
1016         VkImageAspectFlagBits aspect = VK_IMAGE_ASPECT_COLOR_BIT;
1017 
1018         /* Image for the DS attachment */
1019         if (i >= colorAttachmentNum)
1020         {
1021             attFormat = m_testCase->checkAndGetDSFormat(context);
1022             DE_ASSERT(attFormat != VK_FORMAT_UNDEFINED);
1023             colorImageCreateInfo.format = attFormat;
1024             colorImageCreateInfo.usage  = AttachmentAccessOrderTestCase::getDSImageUsageFlags();
1025             aspect                      = m_testCase->getDSAspect();
1026         }
1027 
1028         m_inputAtt.push_back(createImage(vk, device, &colorImageCreateInfo, DE_NULL));
1029         VkImageViewCreateInfo colorTargetViewInfo = {
1030             VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
1031             DE_NULL,                                  // const void* pNext;
1032             0u,                                       // VkImageViewCreateFlags flags;
1033             *m_inputAtt.back(),                       // VkImage image;
1034             VK_IMAGE_VIEW_TYPE_2D,                    // VkImageViewType viewType;
1035             attFormat,                                // VkFormat format;
1036             makeComponentMappingRGBA(),               // VkComponentMapping components;
1037             {
1038                 (VkImageAspectFlags)aspect, // VkImageAspectFlags aspectMask;
1039                 0u,                         // uint32_t baseMipLevel;
1040                 1u,                         // uint32_t mipLevels;
1041                 0u,                         // uint32_t baseArrayLayer;
1042                 1u,                         // uint32_t arraySize;
1043             },                              // VkImageSubresourceRange subresourceRange;
1044         };
1045         m_inputAttMemory.push_back(
1046             allocator.allocate(getImageMemoryRequirements(vk, device, *m_inputAtt.back()), MemoryRequirement::Any));
1047         VK_CHECK(vk.bindImageMemory(device, *m_inputAtt.back(), m_inputAttMemory.back()->getMemory(),
1048                                     m_inputAttMemory.back()->getOffset()));
1049         m_inputAttView.push_back(createImageView(vk, device, &colorTargetViewInfo));
1050 
1051         m_attachmentReferences.push_back({(uint32_t)views.size(), VK_IMAGE_LAYOUT_GENERAL});
1052         views.push_back(*m_inputAttView.back());
1053     }
1054 }
1055 
createPipeline(VkRenderPass renderPass,Context & context)1056 void AttachmentAccessOrderTestInstance::RenderSubpass::createPipeline(VkRenderPass renderPass, Context &context)
1057 {
1058 
1059     const DeviceInterface &vk = context.getDeviceInterface();
1060     const VkDevice device     = context.getDevice();
1061     const Unique<VkShaderModule> vs(
1062         createShaderModule(vk, device, context.getBinaryCollection().get(m_subpass == 0 ? "vert1" : "vert2"), 0));
1063     const Unique<VkShaderModule> fs(
1064         createShaderModule(vk, device, context.getBinaryCollection().get(m_subpass == 0 ? "frag" : "frag_resolve"), 0));
1065 
1066     const VkVertexInputBindingDescription vertexInputBindingDescription = {
1067         0,                           // uint32_t binding;
1068         sizeof(tcu::Vec2),           // uint32_t strideInBytes;
1069         VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputStepRate stepRate;
1070     };
1071 
1072     const VkVertexInputAttributeDescription vertexInputAttributeDescription = {
1073         0u,                      // uint32_t location;
1074         0u,                      // uint32_t binding;
1075         VK_FORMAT_R32G32_SFLOAT, // VkFormat format;
1076         0u,                      // uint32_t offsetInBytes;
1077     };
1078 
1079     const VkPipelineVertexInputStateCreateInfo vertexInputStateParams = {
1080         VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
1081         DE_NULL,                                                   // const void* pNext;
1082         0,                                                         // VkPipelineVertexInputStateCreateFlags flags;
1083         1u,                                                        // uint32_t bindingCount;
1084         &vertexInputBindingDescription,   // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
1085         1u,                               // uint32_t attributeCount;
1086         &vertexInputAttributeDescription, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
1087     };
1088 
1089     const std::vector<VkViewport> viewports(1, {0, 0, WIDTH, HEIGHT, 0, 1});
1090     const std::vector<VkRect2D> scissors(1, {{0, 0}, {WIDTH, HEIGHT}});
1091     const VkPipelineRasterizationStateCreateInfo rasterizationStateInfo = {
1092         VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
1093         DE_NULL,                                                    // const void* pNext;
1094         0u,                                                         // VkPipelineRasterizationStateCreateFlags flags;
1095         VK_FALSE,                                                   // VkBool32 depthClampEnable;
1096         VK_FALSE,                                                   // VkBool32 rasterizerDiscardEnable;
1097         VK_POLYGON_MODE_FILL,                                       // VkPolygonMode polygonMode;
1098         VK_CULL_MODE_NONE,                                          // VkCullModeFlags cullMode;
1099         VK_FRONT_FACE_COUNTER_CLOCKWISE,                            // VkFrontFace frontFace;
1100         VK_FALSE,                                                   // VkBool32 depthBiasEnable;
1101         0.0f,                                                       // float depthBiasConstantFactor;
1102         0.0f,                                                       // float depthBiasClamp;
1103         0.0f,                                                       // float depthBiasSlopeFactor;
1104         1.0f,                                                       // float lineWidth;
1105     };
1106     const VkPipelineMultisampleStateCreateInfo multisampleStateParams = {
1107         VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
1108         DE_NULL,                                                  // const void* pNext;
1109         0u,                                                       // VkPipelineMultisampleStateCreateFlags flags;
1110         m_sampleCount,                                            // VkSampleCountFlagBits rasterizationSamples;
1111         VK_TRUE,                                                  // VkBool32 sampleShadingEnable;
1112         1.0f,                                                     // float minSampleShading;
1113         DE_NULL,                                                  // const VkSampleMask* pSampleMask;
1114         VK_FALSE,                                                 // VkBool32 alphaToCoverageEnable;
1115         VK_FALSE                                                  // VkBool32 alphaToOneEnable;
1116     };
1117     std::vector<VkPipelineColorBlendAttachmentState> colorBlendAttachmentState(
1118         m_colorAttNum,
1119         {
1120             false,                                                // VkBool32 blendEnable;
1121             VK_BLEND_FACTOR_ONE,                                  // VkBlend srcBlendColor;
1122             VK_BLEND_FACTOR_ONE,                                  // VkBlend destBlendColor;
1123             VK_BLEND_OP_ADD,                                      // VkBlendOp blendOpColor;
1124             VK_BLEND_FACTOR_ONE,                                  // VkBlend srcBlendAlpha;
1125             VK_BLEND_FACTOR_ONE,                                  // VkBlend destBlendAlpha;
1126             VK_BLEND_OP_ADD,                                      // VkBlendOp blendOpAlpha;
1127             (VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT) // VkChannelFlags channelWriteMask;
1128         });
1129 
1130     const VkPipelineColorBlendStateCreateInfo colorBlendStateParams = {
1131         VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
1132         DE_NULL,                                                  // const void* pNext;
1133         /* always needed */
1134         m_testCase->getBlendStateFlags(),           // VkPipelineColorBlendStateCreateFlags flags;
1135         false,                                      // VkBool32 logicOpEnable;
1136         VK_LOGIC_OP_COPY,                           // VkLogicOp logicOp;
1137         (uint32_t)colorBlendAttachmentState.size(), // uint32_t attachmentCount;
1138         colorBlendAttachmentState.data(),           // const VkPipelineColorBlendAttachmentState* pAttachments;
1139         {0.0f, 0.0f, 0.0f, 0.0f},                   // float blendConst[4];
1140     };
1141 
1142     VkStencilOpState stencilOpState = {
1143         VK_STENCIL_OP_ZERO,               // VkStencilOp failOp;
1144         VK_STENCIL_OP_INCREMENT_AND_WRAP, // VkStencilOp passOp;
1145         VK_STENCIL_OP_INCREMENT_AND_WRAP, // VkStencilOp depthFailOp;
1146         VK_COMPARE_OP_ALWAYS,             // VkCompareOp compareOp;
1147         0xff,                             // uint32_t compareMask;
1148         0xff,                             // uint32_t writeMask;
1149         0,                                // uint32_t reference;
1150     };
1151     VkPipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo = {
1152         VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
1153         // VkStructureType sType;
1154         DE_NULL, // const void* pNext;
1155         m_testCase->getDSStateFlags(),
1156         // VkPipelineDepthStencilStateCreateFlags flags;
1157         VK_TRUE,              // VkBool32 depthTestEnable;
1158         VK_TRUE,              // VkBool32 depthWriteEnable;
1159         VK_COMPARE_OP_ALWAYS, // VkCompareOp depthCompareOp;
1160         VK_FALSE,             // VkBool32 depthBoundsTestEnable;
1161         VK_TRUE,              // VkBool32 stencilTestEnable;
1162         stencilOpState,       // VkStencilOpState front;
1163         stencilOpState,       // VkStencilOpState back;
1164         0.0f,                 // float minDepthBounds;
1165         1.0f,                 // float maxDepthBounds;
1166     };
1167 
1168     m_pipeline = makeGraphicsPipeline(
1169         vk,                // const DeviceInterface&                            vk
1170         device,            // const VkDevice                                    device
1171         *m_pipelineLayout, // const VkPipelineLayout                            pipelineLayout
1172         *vs,               // const VkShaderModule                                vertexShaderModule
1173         DE_NULL,           // const VkShaderModule                                tessellationControlShaderModule
1174         DE_NULL,           // const VkShaderModule                                tessellationEvalShaderModule
1175         DE_NULL,           // const VkShaderModule                                geometryShaderModule
1176         *fs,               // const VkShaderModule                                fragmentShaderModule
1177         renderPass,        // const VkRenderPass                                renderPass
1178         viewports,         // const std::vector<VkViewport>&                    viewports
1179         scissors,          // const std::vector<VkRect2D>&                        scissors
1180         VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // const VkPrimitiveTopology                        topology
1181         m_subpass,                           // const uint32_t                                    subpass
1182         0u,                                  // const uint32_t                                    patchControlPoints
1183         &vertexInputStateParams,      // const VkPipelineVertexInputStateCreateInfo*        vertexInputStateCreateInfo
1184         &rasterizationStateInfo,      // const VkPipelineRasterizationStateCreateInfo*    rasterizationStateCreateInfo
1185         &multisampleStateParams,      // const VkPipelineMultisampleStateCreateInfo*        multisampleStateCreateInfo
1186         &depthStencilStateCreateInfo, // const VkPipelineDepthStencilStateCreateInfo*        depthStencilStateCreateInfo,
1187         &colorBlendStateParams,       // const VkPipelineColorBlendStateCreateInfo*        colorBlendStateCreateInfo,
1188         DE_NULL);                     // const VkPipelineDynamicStateCreateInfo*            dynamicStateCreateInfo
1189 }
1190 
makeSampler(const DeviceInterface & vk,const VkDevice & device)1191 static Move<VkSampler> makeSampler(const DeviceInterface &vk, const VkDevice &device)
1192 {
1193     const VkSamplerCreateInfo createInfo = {
1194         VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,   // VkStructureType sType;
1195         DE_NULL,                                 // const void* pNext;
1196         0u,                                      // VkSamplerCreateFlags flags;
1197         VK_FILTER_NEAREST,                       // VkFilter magFilter;
1198         VK_FILTER_NEAREST,                       // VkFilter minFilter;
1199         VK_SAMPLER_MIPMAP_MODE_LINEAR,           // VkSamplerMipmapMode mipmapMode;
1200         VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,   // VkSamplerAddressMode addressModeU;
1201         VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,   // VkSamplerAddressMode addressModeV;
1202         VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,   // VkSamplerAddressMode addressModeW;
1203         0.0f,                                    // float mipLodBias;
1204         VK_FALSE,                                // VkBool32 anisotropyEnable;
1205         1.0f,                                    // float maxAnisotropy;
1206         VK_FALSE,                                // VkBool32 compareEnable;
1207         VK_COMPARE_OP_ALWAYS,                    // VkCompareOp compareOp;
1208         0.0f,                                    // float minLod;
1209         0.0f,                                    // float maxLod;
1210         VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, // VkBorderColor borderColor;
1211         VK_FALSE                                 // VkBool32 unnormalizedCoordinates;
1212     };
1213 
1214     return createSampler(vk, device, &createInfo);
1215 }
1216 
makeDescriptorSetLayout(const DeviceInterface & vk,const VkDevice device,uint32_t attNum)1217 static Move<VkDescriptorSetLayout> makeDescriptorSetLayout(const DeviceInterface &vk, const VkDevice device,
1218                                                            uint32_t attNum)
1219 {
1220     vector<VkDescriptorSetLayoutBinding> bindings(attNum,
1221                                                   {
1222                                                       0,                                   // binding
1223                                                       VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, // descriptorType
1224                                                       1u,                                  // descriptorCount
1225                                                       VK_SHADER_STAGE_FRAGMENT_BIT,        // stageFlags
1226                                                       DE_NULL,                             // pImmutableSamplers
1227                                                   });
1228     for (uint32_t i = 0; i < attNum; i++)
1229     {
1230         bindings[i].binding = i;
1231     }
1232 
1233     const VkDescriptorSetLayoutCreateInfo layoutCreateInfo = {
1234         VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
1235         DE_NULL,         // pNext
1236         0u,              // flags
1237         attNum,          // bindingCount
1238         bindings.data(), // pBindings
1239     };
1240 
1241     return vk::createDescriptorSetLayout(vk, device, &layoutCreateInfo);
1242 }
writeDescriptorSets()1243 void AttachmentAccessOrderTestInstance::writeDescriptorSets()
1244 {
1245     uint32_t attNum = m_testCase->getInputAttachmentNum();
1246     for (uint32_t i = 0; i < attNum; i++)
1247     {
1248         VkDescriptorImageInfo img_info = {};
1249         img_info.sampler               = *m_sampler;
1250         img_info.imageView             = *m_subpasses[0].m_inputAttView[i];
1251         img_info.imageLayout           = VK_IMAGE_LAYOUT_GENERAL;
1252 
1253         VkWriteDescriptorSet write = {};
1254         write.sType                = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1255         write.dstSet               = *m_descSet;
1256         write.dstBinding           = i;
1257         write.dstArrayElement      = 0;
1258         write.descriptorCount      = 1;
1259         write.descriptorType       = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
1260         write.pImageInfo           = &img_info;
1261 
1262         m_vk.updateDescriptorSets(m_context.getDevice(), 1u, &write, 0u, DE_NULL);
1263     }
1264 }
1265 
addDependency(vector<VkSubpassDependency> & dependencies,uint32_t source,uint32_t dst,VkPipelineStageFlags pipelineFlags,VkAccessFlags accessFlags)1266 void AttachmentAccessOrderTestInstance::addDependency(vector<VkSubpassDependency> &dependencies, uint32_t source,
1267                                                       uint32_t dst, VkPipelineStageFlags pipelineFlags,
1268                                                       VkAccessFlags accessFlags)
1269 {
1270     dependencies.push_back({
1271         source,                                //uint32_t srcSubpass;
1272         dst,                                   //uint32_t dstSubpass;
1273         pipelineFlags,                         //VkPipelineStageFlags srcStageMask;
1274         VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, //VkPipelineStageFlags dstStageMask;
1275         accessFlags,                           //VkAccessFlags srcAccessMask;
1276         VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,   //VkAccessFlags dstAccessMask;
1277         VK_DEPENDENCY_BY_REGION_BIT,           //VkDependencyFlags dependencyFlags;
1278     });
1279 }
createRenderPass(VkFormat attFormat)1280 Move<VkRenderPass> AttachmentAccessOrderTestInstance::createRenderPass(VkFormat attFormat)
1281 {
1282     const VkDevice device = m_context.getDevice();
1283     vector<VkAttachmentDescription> attachmentDescs;
1284     for (uint32_t subpass = 0; subpass < 2; subpass++)
1285     {
1286         for (uint32_t i = 0; i < m_subpasses[subpass].getInputAttachmentNum(); i++)
1287         {
1288             VkFormat format = attFormat;
1289             if (i >= m_subpasses[subpass].getColorAttachmentNum())
1290             {
1291                 format = m_testCase->checkAndGetDSFormat(m_context);
1292                 DE_ASSERT(format != VK_FORMAT_UNDEFINED);
1293             }
1294             attachmentDescs.push_back({
1295                 0,                                  // VkAttachmentDescriptionFlags flags;
1296                 format,                             // VkFormat format;
1297                 m_subpasses[subpass].m_sampleCount, // VkSampleCountFlagBits samples;
1298                 VK_ATTACHMENT_LOAD_OP_LOAD,         // VkAttachmentLoadOp loadOp;
1299                 VK_ATTACHMENT_STORE_OP_STORE,       // VkAttachmentStoreOp storeOp;
1300                 VK_ATTACHMENT_LOAD_OP_LOAD,         // VkAttachmentLoadOp stencilLoadOp;
1301                 VK_ATTACHMENT_STORE_OP_STORE,       // VkAttachmentStoreOp stencilStoreOp;
1302                 VK_IMAGE_LAYOUT_GENERAL,            // VkImageLayout initialLayout;
1303                 VK_IMAGE_LAYOUT_GENERAL,            // VkImageLayout finalLayout;
1304             });
1305         }
1306     }
1307 
1308     std::vector<VkSubpassDescription> subpasses(2, VkSubpassDescription{});
1309 
1310     subpasses[0].pipelineBindPoint       = VK_PIPELINE_BIND_POINT_GRAPHICS;
1311     subpasses[0].inputAttachmentCount    = m_subpasses[0].getInputAttachmentNum();
1312     subpasses[0].pInputAttachments       = m_subpasses[0].m_attachmentReferences.data();
1313     subpasses[0].colorAttachmentCount    = m_subpasses[0].getColorAttachmentNum();
1314     subpasses[0].pColorAttachments       = m_subpasses[0].m_attachmentReferences.data();
1315     subpasses[0].pDepthStencilAttachment = m_subpasses[0].getDepthStencilAttachment();
1316 
1317     subpasses[1].pipelineBindPoint    = VK_PIPELINE_BIND_POINT_GRAPHICS;
1318     subpasses[1].inputAttachmentCount = m_subpasses[0].getColorAttachmentNum();
1319     subpasses[1].pInputAttachments    = m_subpasses[0].m_attachmentReferences.data();
1320     subpasses[1].colorAttachmentCount = m_subpasses[1].getColorAttachmentNum();
1321     subpasses[1].pColorAttachments    = m_subpasses[1].m_attachmentReferences.data();
1322 
1323     /* self dependency for subpass 0 and dependency from subpass 0 to 1 */
1324     vector<VkSubpassDependency> dependencies;
1325     addDependency(dependencies, 0, 1, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
1326                   VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
1327     if (m_testCase->m_explicitSync)
1328     {
1329         addDependency(dependencies, 0, 0, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
1330                       VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
1331         if (m_testCase->hasDepthStencil())
1332         {
1333             const auto fragTests =
1334                 (VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT);
1335             addDependency(dependencies, 0, 0, fragTests, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT);
1336         }
1337     }
1338     else
1339     {
1340         subpasses[0].flags = VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_COLOR_ACCESS_BIT_ARM;
1341         subpasses[1].flags = VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_COLOR_ACCESS_BIT_ARM;
1342         if (m_testCase->hasDepth())
1343         {
1344             subpasses[0].flags |= VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_DEPTH_ACCESS_BIT_ARM;
1345             subpasses[1].flags |= VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_DEPTH_ACCESS_BIT_ARM;
1346         }
1347         else if (m_testCase->hasStencil())
1348         {
1349             subpasses[0].flags |= VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_STENCIL_ACCESS_BIT_ARM;
1350             subpasses[1].flags |= VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_STENCIL_ACCESS_BIT_ARM;
1351         }
1352     }
1353 
1354     VkRenderPassCreateInfo renderPassCreateInfo = {
1355         VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
1356         NULL,                                      // const void* pNext;
1357         0,                                         // VkRenderPassCreateFlags flags;
1358         (uint32_t)attachmentDescs.size(),          // uint32_t attachmentCount;
1359         attachmentDescs.data(),                    // const VkAttachmentDescription* pAttachments;
1360         (uint32_t)subpasses.size(),                // uint32_t subpassCount;
1361         subpasses.data(),                          // const VkSubpassDescription* pSubpasses;
1362         (uint32_t)dependencies.size(),             // uint32_t dependencyCount;
1363         dependencies.data(),                       // const VkSubpassDependency* pDependencies;
1364     };
1365 
1366     return ::createRenderPass(m_vk, device, &renderPassCreateInfo);
1367 }
1368 
createVertexBuffer()1369 void AttachmentAccessOrderTestInstance::createVertexBuffer()
1370 {
1371     uint32_t primitiveNum           = m_testCase->m_overlapPrimitives ? AttachmentAccessOrderTestCase::ELEM_NUM * 2 : 2;
1372     const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1373     const VkDevice device           = m_context.getDevice();
1374     Allocator &allocator            = m_context.getDefaultAllocator();
1375     std::vector<tcu::Vec2> vbo(3 * primitiveNum);
1376     for (uint32_t i = 0; i < primitiveNum / 2; i++)
1377     {
1378         vbo[i * 6 + 0] = {-1, -1};
1379         vbo[i * 6 + 1] = {1, -1};
1380         vbo[i * 6 + 2] = {-1, 1};
1381         vbo[i * 6 + 3] = {1, 1};
1382         vbo[i * 6 + 4] = {-1, 1};
1383         vbo[i * 6 + 5] = {1, -1};
1384     }
1385 
1386     const size_t dataSize = vbo.size() * sizeof(tcu::Vec2);
1387     {
1388         const VkBufferCreateInfo vertexBufferParams = {
1389             VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
1390             DE_NULL,                              // const void* pNext;
1391             0u,                                   // VkBufferCreateFlags flags;
1392             dataSize,                             // VkDeviceSize size;
1393             VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,    // VkBufferUsageFlags usage;
1394             VK_SHARING_MODE_EXCLUSIVE,            // VkSharingMode sharingMode;
1395             1u,                                   // uint32_t queueFamilyCount;
1396             &queueFamilyIndex                     // const uint32_t* pQueueFamilyIndices;
1397         };
1398         m_vertexBuffer       = createBuffer(m_vk, device, &vertexBufferParams);
1399         m_vertexBufferMemory = allocator.allocate(getBufferMemoryRequirements(m_vk, device, *m_vertexBuffer),
1400                                                   MemoryRequirement::HostVisible);
1401 
1402         VK_CHECK(m_vk.bindBufferMemory(device, *m_vertexBuffer, m_vertexBufferMemory->getMemory(),
1403                                        m_vertexBufferMemory->getOffset()));
1404     }
1405 
1406     /* Load vertices into vertex buffer */
1407     deMemcpy(m_vertexBufferMemory->getHostPtr(), vbo.data(), dataSize);
1408     flushAlloc(m_vk, device, *m_vertexBufferMemory);
1409 }
1410 
createResultBuffer()1411 void AttachmentAccessOrderTestInstance::createResultBuffer()
1412 {
1413     const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1414     const VkDevice device           = m_context.getDevice();
1415     Allocator &allocator            = m_context.getDefaultAllocator();
1416     /* result buffer */
1417     const VkBufferCreateInfo resultBufferInfo = {
1418         VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
1419         DE_NULL,                              // const void* pNext;
1420         0u,                                   // VkBufferCreateFlags flags;
1421         WIDTH * HEIGHT * sizeof(tcu::UVec2),  // VkDeviceSize size;
1422         VK_BUFFER_USAGE_TRANSFER_DST_BIT,     // VkBufferUsageFlags usage;
1423         VK_SHARING_MODE_EXCLUSIVE,            // VkSharingMode sharingMode;
1424         1u,                                   // uint32_t queueFamilyCount;
1425         &queueFamilyIndex                     // const uint32_t* pQueueFamilyIndices;
1426     };
1427     m_resultBuffer = createBuffer(m_vk, device, &resultBufferInfo);
1428     m_resultBufferMemory =
1429         allocator.allocate(getBufferMemoryRequirements(m_vk, device, *m_resultBuffer), MemoryRequirement::HostVisible);
1430 
1431     VK_CHECK(m_vk.bindBufferMemory(device, *m_resultBuffer, m_resultBufferMemory->getMemory(),
1432                                    m_resultBufferMemory->getOffset()));
1433 }
1434 
AttachmentAccessOrderTestInstance(Context & context,const AttachmentAccessOrderTestCase * testCase)1435 AttachmentAccessOrderTestInstance::AttachmentAccessOrderTestInstance(Context &context,
1436                                                                      const AttachmentAccessOrderTestCase *testCase)
1437     : TestInstance(context)
1438     , m_testCase(testCase)
1439     , m_vk(m_context.getDeviceInterface())
1440     , m_subpasses(2)
1441 {
1442     const VkDevice device           = m_context.getDevice();
1443     const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1444 
1445     m_descSetLayout = makeDescriptorSetLayout(m_vk, device, m_testCase->getInputAttachmentNum());
1446 
1447     m_descPool = DescriptorPoolBuilder()
1448                      .addType(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, m_testCase->getInputAttachmentNum())
1449                      .build(m_vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1450 
1451     m_descSet = makeDescriptorSet(m_vk, device, *m_descPool, *m_descSetLayout, nullptr);
1452 
1453     vector<VkImageView> attachmentHandles;
1454     VkDescriptorSetLayout dsetLayout = *m_descSetLayout;
1455 
1456     m_subpasses[0].createAttachments(0, m_testCase->getInputAttachmentNum(), m_testCase->getColorAttachmentNum(),
1457                                      m_testCase->m_sampleCount, m_context, attachmentHandles, &dsetLayout, m_testCase);
1458     m_subpasses[1].createAttachments(1, 1, 1, VK_SAMPLE_COUNT_1_BIT, m_context, attachmentHandles, &dsetLayout,
1459                                      m_testCase);
1460 
1461     m_sampler = makeSampler(m_vk, device);
1462 
1463     writeDescriptorSets();
1464     m_renderPass = createRenderPass(m_testCase->getColorFormat());
1465 
1466     m_framebuffer = makeFramebuffer(m_vk, device, *m_renderPass, (uint32_t)attachmentHandles.size(),
1467                                     attachmentHandles.data(), WIDTH, HEIGHT, 1);
1468 
1469     m_subpasses[0].createPipeline(*m_renderPass, m_context);
1470     m_subpasses[1].createPipeline(*m_renderPass, m_context);
1471 
1472     createVertexBuffer();
1473 
1474     createResultBuffer();
1475 
1476     m_cmdPool   = createCommandPool(m_vk, device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
1477     m_cmdBuffer = allocateCommandBuffer(m_vk, device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1478 }
1479 
~AttachmentAccessOrderTestInstance(void)1480 AttachmentAccessOrderTestInstance::~AttachmentAccessOrderTestInstance(void)
1481 {
1482 }
1483 
addPipelineBarrier(VkCommandBuffer cmdBuffer,VkImage image,VkImageLayout oldLayout,VkImageLayout newLayout,VkAccessFlags srcAccessMask,VkAccessFlags dstAccessMask,VkPipelineStageFlags srcStageMask,VkPipelineStageFlags dstStageMask,VkImageAspectFlags aspect)1484 void AttachmentAccessOrderTestInstance::addPipelineBarrier(VkCommandBuffer cmdBuffer, VkImage image,
1485                                                            VkImageLayout oldLayout, VkImageLayout newLayout,
1486                                                            VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask,
1487                                                            VkPipelineStageFlags srcStageMask,
1488                                                            VkPipelineStageFlags dstStageMask, VkImageAspectFlags aspect)
1489 {
1490     VkImageMemoryBarrier barrier = {
1491         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1492         DE_NULL,                                // const void* pNext;
1493         srcAccessMask,                          // VkAccessFlags srcAccessMask;
1494         dstAccessMask,                          // VkAccessFlags dstAccessMask;
1495         oldLayout,                              // VkImageLayout oldLayout;
1496         newLayout,                              // VkImageLayout newLayout;
1497         VK_QUEUE_FAMILY_IGNORED,                // uint32_t srcQueueFamilyIndex;
1498         VK_QUEUE_FAMILY_IGNORED,                // uint32_t dstQueueFamilyIndex;
1499         image,                                  // VkImage image;
1500         {
1501             aspect, //VkImageAspectFlags aspectMask;
1502             0u,     //uint32_t baseMipLevel;
1503             1u,     //uint32_t levelCount;
1504             0u,     //uint32_t baseArrayLayer;
1505             1u,     //uint32_t layerCount;
1506         },          // VkImageSubresourceRange subresourceRange;
1507     };
1508 
1509     m_vk.cmdPipelineBarrier(cmdBuffer, srcStageMask, dstStageMask, VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 0, nullptr,
1510                             1, &barrier);
1511 }
addClearColor(VkCommandBuffer cmdBuffer,VkImage image)1512 void AttachmentAccessOrderTestInstance::addClearColor(VkCommandBuffer cmdBuffer, VkImage image)
1513 {
1514     VkClearColorValue clearColor;
1515     clearColor.float32[0] = 0.0;
1516     clearColor.float32[1] = 0.0;
1517     clearColor.float32[2] = 0.0;
1518     clearColor.float32[3] = 1.0;
1519 
1520     const VkImageSubresourceRange subresourceRange = {
1521         VK_IMAGE_ASPECT_COLOR_BIT, //VkImageAspectFlags aspectMask;
1522         0u,                        //uint32_t baseMipLevel;
1523         1u,                        //uint32_t levelCount;
1524         0u,                        //uint32_t baseArrayLayer;
1525         1u,                        //uint32_t layerCount;
1526     };
1527 
1528     m_vk.cmdClearColorImage(cmdBuffer, image, VK_IMAGE_LAYOUT_GENERAL, &clearColor, 1, &subresourceRange);
1529 }
1530 
addClearDepthStencil(VkCommandBuffer cmdBuffer,VkImage image)1531 void AttachmentAccessOrderTestInstance::addClearDepthStencil(VkCommandBuffer cmdBuffer, VkImage image)
1532 {
1533     VkClearDepthStencilValue clearValue;
1534     clearValue.depth   = 0.0;
1535     clearValue.stencil = 0;
1536 
1537     const VkImageSubresourceRange subresourceRange = {
1538         VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, //VkImageAspectFlags aspectMask;
1539         0u,                                                      //uint32_t baseMipLevel;
1540         1u,                                                      //uint32_t levelCount;
1541         0u,                                                      //uint32_t baseArrayLayer;
1542         1u,                                                      //uint32_t layerCount;
1543     };
1544 
1545     m_vk.cmdClearDepthStencilImage(cmdBuffer, image, VK_IMAGE_LAYOUT_GENERAL, &clearValue, 1, &subresourceRange);
1546 }
1547 
iterate(void)1548 tcu::TestStatus AttachmentAccessOrderTestInstance::iterate(void)
1549 {
1550     const VkQueue queue   = m_context.getUniversalQueue();
1551     const VkDevice device = m_context.getDevice();
1552 
1553     beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);
1554 
1555     for (uint32_t i = 0; i < m_subpasses.size(); i++)
1556     {
1557         for (uint32_t j = 0; j < m_subpasses[i].getColorAttachmentNum(); j++)
1558         {
1559             addPipelineBarrier(*m_cmdBuffer, *m_subpasses[i].m_inputAtt[j], VK_IMAGE_LAYOUT_UNDEFINED,
1560                                VK_IMAGE_LAYOUT_GENERAL, 0u, VK_ACCESS_TRANSFER_WRITE_BIT,
1561                                VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
1562 
1563             addClearColor(*m_cmdBuffer, *m_subpasses[i].m_inputAtt[j]);
1564         }
1565         for (uint32_t j = m_subpasses[i].getColorAttachmentNum(); j < m_subpasses[i].getInputAttachmentNum(); j++)
1566         {
1567             addPipelineBarrier(*m_cmdBuffer, *m_subpasses[i].m_inputAtt[j], VK_IMAGE_LAYOUT_UNDEFINED,
1568                                VK_IMAGE_LAYOUT_GENERAL, 0u, VK_ACCESS_TRANSFER_WRITE_BIT,
1569                                VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
1570                                VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT);
1571             addClearDepthStencil(*m_cmdBuffer, *m_subpasses[i].m_inputAtt[j]);
1572         }
1573     }
1574 
1575     const vk::VkAccessFlags colorOnlyAccessMask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT |
1576                                                   VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
1577                                                   VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
1578     const vk::VkAccessFlags depthStencilColorAccessMask = colorOnlyAccessMask |
1579                                                           VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
1580                                                           VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
1581     const vk::VkAccessFlags dstAccessMask =
1582         m_testCase->hasDepthStencil() ? depthStencilColorAccessMask : colorOnlyAccessMask;
1583 
1584     const VkMemoryBarrier memBarrier = {VK_STRUCTURE_TYPE_MEMORY_BARRIER, DE_NULL, VK_ACCESS_TRANSFER_WRITE_BIT,
1585                                         dstAccessMask};
1586 
1587     const vk::VkPipelineStageFlags colorOnlyStageFlags =
1588         VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
1589     const vk::VkPipelineStageFlags depthStencilColorStageFlags =
1590         colorOnlyStageFlags | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
1591     const vk::VkPipelineStageFlags dstStageFlags =
1592         m_testCase->hasDepthStencil() ? depthStencilColorStageFlags : colorOnlyStageFlags;
1593     m_vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, dstStageFlags, 0, 1, &memBarrier, 0, DE_NULL,
1594                             0, DE_NULL);
1595 
1596     const VkRect2D renderArea = makeRect2D(WIDTH, HEIGHT);
1597     beginRenderPass(m_vk, *m_cmdBuffer, *m_renderPass, *m_framebuffer, renderArea);
1598 
1599     const VkDeviceSize vertexBufferOffset = 0;
1600     const VkBuffer vertexBuffer           = *m_vertexBuffer;
1601 
1602     m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
1603     m_vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_subpasses[0].m_pipeline);
1604     VkDescriptorSet dset = *m_descSet;
1605     m_vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_subpasses[0].m_pipelineLayout, 0, 1,
1606                                &dset, 0, DE_NULL);
1607 
1608     uint32_t numDraws      = m_testCase->m_overlapDraws ? AttachmentAccessOrderTestCase::ELEM_NUM : 1;
1609     uint32_t numPrimitives = m_testCase->m_overlapPrimitives ? 2 * AttachmentAccessOrderTestCase::ELEM_NUM : 2;
1610     uint32_t numInstances  = m_testCase->m_overlapInstances ? AttachmentAccessOrderTestCase::ELEM_NUM : 1;
1611 
1612     for (uint32_t i = 0; i < numDraws; i++)
1613     {
1614         m_vk.cmdPushConstants(
1615             *m_cmdBuffer, *m_subpasses[0].m_pipelineLayout,
1616             VK_SHADER_STAGE_FRAGMENT_BIT | (m_testCase->hasDepthStencil() ? VK_SHADER_STAGE_VERTEX_BIT : 0), 0, 4, &i);
1617         for (uint32_t j = 0; m_testCase->m_explicitSync && i != 0 && j < m_subpasses[0].getColorAttachmentNum(); j++)
1618         {
1619             addPipelineBarrier(*m_cmdBuffer, *m_subpasses[0].m_inputAtt[j], VK_IMAGE_LAYOUT_GENERAL,
1620                                VK_IMAGE_LAYOUT_GENERAL, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
1621                                VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
1622                                VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
1623         }
1624         for (uint32_t j = m_subpasses[0].getColorAttachmentNum();
1625              m_testCase->m_explicitSync && i != 0 && j < m_subpasses[0].getInputAttachmentNum(); j++)
1626         {
1627             const auto fragTests =
1628                 (VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT);
1629             addPipelineBarrier(*m_cmdBuffer, *m_subpasses[0].m_inputAtt[j], VK_IMAGE_LAYOUT_GENERAL,
1630                                VK_IMAGE_LAYOUT_GENERAL, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
1631                                VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, fragTests, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
1632                                VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT);
1633         }
1634         m_vk.cmdDraw(*m_cmdBuffer, numPrimitives * 3, numInstances, 0, 0);
1635     }
1636 
1637     m_vk.cmdNextSubpass(*m_cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
1638 
1639     m_vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_subpasses[1].m_pipeline);
1640 
1641     m_vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_subpasses[1].m_pipelineLayout, 0, 1,
1642                                &dset, 0, DE_NULL);
1643 
1644     m_vk.cmdDraw(*m_cmdBuffer, 6, 1, 0, 0);
1645 
1646     endRenderPass(m_vk, *m_cmdBuffer);
1647 
1648     copyImageToBuffer(m_vk, *m_cmdBuffer, *m_subpasses[1].m_inputAtt[0], *m_resultBuffer, tcu::IVec2(WIDTH, HEIGHT),
1649                       VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL);
1650 
1651     endCommandBuffer(m_vk, *m_cmdBuffer);
1652 
1653     submitCommandsAndWait(m_vk, device, queue, m_cmdBuffer.get());
1654 
1655     return validateResults(numDraws, numPrimitives, numInstances);
1656 }
1657 
validateResults(uint32_t numDraws,uint32_t numPrimitives,uint32_t numInstances)1658 tcu::TestStatus AttachmentAccessOrderTestInstance::validateResults(uint32_t numDraws, uint32_t numPrimitives,
1659                                                                    uint32_t numInstances)
1660 {
1661     const VkDevice device = m_context.getDevice();
1662     qpTestResult res      = QP_TEST_RESULT_PASS;
1663 
1664     invalidateAlloc(m_vk, device, *m_resultBufferMemory);
1665     if (m_testCase->m_integerFormat)
1666     {
1667         tcu::UVec2 *resBuf = static_cast<tcu::UVec2 *>(m_resultBufferMemory->getHostPtr());
1668 
1669         for (uint32_t y = 0; y < HEIGHT && res == QP_TEST_RESULT_PASS; y++)
1670         {
1671             for (uint32_t x = 0; x < WIDTH && res == QP_TEST_RESULT_PASS; x++)
1672             {
1673                 tcu::UVec2 pixel = resBuf[y * WIDTH + x];
1674                 if (pixel[0] != 0 || pixel[1] != numDraws * numPrimitives / 2 * numInstances)
1675                 {
1676                     res = QP_TEST_RESULT_FAIL;
1677                 }
1678             }
1679         }
1680     }
1681     else
1682     {
1683         tcu::Vec2 *resBuf = static_cast<tcu::Vec2 *>(m_resultBufferMemory->getHostPtr());
1684 
1685         for (uint32_t y = 0; y < HEIGHT && res == QP_TEST_RESULT_PASS; y++)
1686         {
1687             for (uint32_t x = 0; x < WIDTH && res == QP_TEST_RESULT_PASS; x++)
1688             {
1689                 tcu::Vec2 pixel = resBuf[y * WIDTH + x];
1690                 if (pixel[0] != 0 || pixel[1] != (float)(numDraws * numPrimitives / 2 * numInstances))
1691                 {
1692                     res = QP_TEST_RESULT_FAIL;
1693                 }
1694             }
1695         }
1696     }
1697 
1698     return tcu::TestStatus(res, qpGetTestResultName(res));
1699 }
1700 
1701 } // namespace
1702 
createRasterizationOrderAttachmentAccessTestVariations(tcu::TestContext & testCtx,tcu::TestCaseGroup * gr,const string & prefix_name,const string & prefix_desc,uint32_t inputNum,bool integerFormat,bool depth,bool stencil)1703 static void createRasterizationOrderAttachmentAccessTestVariations(tcu::TestContext &testCtx, tcu::TestCaseGroup *gr,
1704                                                                    const string &prefix_name, const string &prefix_desc,
1705                                                                    uint32_t inputNum, bool integerFormat, bool depth,
1706                                                                    bool stencil)
1707 {
1708     const struct
1709     {
1710         const std::string name;
1711         bool explicitSync;
1712         bool overlapDraws;
1713         bool overlapPrimitives;
1714         bool overlapInstances;
1715     } leafTestCreateParams[] = {
1716         // Basic test with overlapping draw commands with barriers
1717         {
1718             "multi_draw_barriers",
1719             true,
1720             true,
1721             false,
1722             false,
1723         },
1724         // Test with overlapping draw commands without barriers
1725         {
1726             "multi_draw",
1727             false,
1728             true,
1729             false,
1730             false,
1731         },
1732         // Test with a draw command with overlapping primitives
1733         {
1734             "multi_primitives",
1735             false,
1736             false,
1737             true,
1738             false,
1739         },
1740         // Test with a draw command with overlapping instances
1741         {
1742             "multi_instances",
1743             false,
1744             false,
1745             false,
1746             true,
1747         },
1748         // Test with overlapping draw commands, each with overlapping primitives and instances
1749         {
1750             "all",
1751             false,
1752             true,
1753             true,
1754             true,
1755         },
1756     };
1757     constexpr uint32_t leafTestCreateParamsNum = sizeof(leafTestCreateParams) / sizeof(leafTestCreateParams[0]);
1758 
1759     VkSampleCountFlagBits sampleCountValues[] = {
1760         VK_SAMPLE_COUNT_1_BIT,  VK_SAMPLE_COUNT_2_BIT,  VK_SAMPLE_COUNT_4_BIT,  VK_SAMPLE_COUNT_8_BIT,
1761         VK_SAMPLE_COUNT_16_BIT, VK_SAMPLE_COUNT_32_BIT, VK_SAMPLE_COUNT_64_BIT,
1762     };
1763     constexpr uint32_t sampleCountValuesNum = sizeof(sampleCountValues) / sizeof(sampleCountValues[0]);
1764 
1765     for (uint32_t i = 0; i < sampleCountValuesNum; i++)
1766     {
1767         stringstream name;
1768         stringstream desc;
1769         name << prefix_name << "samples_" << AttachmentAccessOrderTestCase::getSampleNum(sampleCountValues[i]);
1770         desc << prefix_desc << AttachmentAccessOrderTestCase::getSampleNum(sampleCountValues[i])
1771              << " samples per pixel";
1772         tcu::TestCaseGroup *subgr = new tcu::TestCaseGroup(testCtx, name.str().c_str());
1773 
1774         for (uint32_t k = 0; k < leafTestCreateParamsNum; k++)
1775         {
1776             if (depth)
1777             {
1778                 subgr->addChild(new AttachmentAccessOrderDepthTestCase(
1779                     testCtx, leafTestCreateParams[k].name, leafTestCreateParams[k].explicitSync,
1780                     leafTestCreateParams[k].overlapDraws, leafTestCreateParams[k].overlapPrimitives,
1781                     leafTestCreateParams[k].overlapInstances, sampleCountValues[i]));
1782             }
1783             else if (stencil)
1784             {
1785                 subgr->addChild(new AttachmentAccessOrderStencilTestCase(
1786                     testCtx, leafTestCreateParams[k].name, leafTestCreateParams[k].explicitSync,
1787                     leafTestCreateParams[k].overlapDraws, leafTestCreateParams[k].overlapPrimitives,
1788                     leafTestCreateParams[k].overlapInstances, sampleCountValues[i]));
1789             }
1790             else
1791             {
1792                 subgr->addChild(new AttachmentAccessOrderColorTestCase(
1793                     testCtx, leafTestCreateParams[k].name, leafTestCreateParams[k].explicitSync,
1794                     leafTestCreateParams[k].overlapDraws, leafTestCreateParams[k].overlapPrimitives,
1795                     leafTestCreateParams[k].overlapInstances, sampleCountValues[i], inputNum, integerFormat));
1796             }
1797         }
1798         gr->addChild(subgr);
1799     }
1800 }
1801 
createRasterizationOrderAttachmentAccessFormatTests(tcu::TestContext & testCtx,tcu::TestCaseGroup * gr,bool integerFormat)1802 static void createRasterizationOrderAttachmentAccessFormatTests(tcu::TestContext &testCtx, tcu::TestCaseGroup *gr,
1803                                                                 bool integerFormat)
1804 {
1805     const uint32_t inputNum[]   = {1, 4, 8};
1806     const uint32_t inputNumSize = sizeof(inputNum) / sizeof(inputNum[0]);
1807 
1808     tcu::TestCaseGroup *formatGr;
1809 
1810     if (integerFormat)
1811     {
1812         formatGr = new tcu::TestCaseGroup(testCtx, "format_integer");
1813     }
1814     else
1815     {
1816         formatGr = new tcu::TestCaseGroup(testCtx, "format_float");
1817     }
1818 
1819     for (uint32_t i = 0; i < inputNumSize; i++)
1820     {
1821         stringstream numName;
1822         stringstream numDesc;
1823         numName << "attachments_" << inputNum[i] << "_";
1824         numDesc << "Tests with " << inputNum[i] << " attachments and ";
1825         createRasterizationOrderAttachmentAccessTestVariations(testCtx, formatGr, numName.str(), numDesc.str(),
1826                                                                inputNum[i], integerFormat, false, false);
1827     }
1828     gr->addChild(formatGr);
1829 }
1830 
createRasterizationOrderAttachmentAccessTests(tcu::TestContext & testCtx)1831 tcu::TestCaseGroup *createRasterizationOrderAttachmentAccessTests(tcu::TestContext &testCtx)
1832 {
1833     /* Add the color tests */
1834     // Rasterization Order Attachment access tests
1835     tcu::TestCaseGroup *gr = new tcu::TestCaseGroup(testCtx, "rasterization_order_attachment_access");
1836     createRasterizationOrderAttachmentAccessFormatTests(testCtx, gr, false);
1837     createRasterizationOrderAttachmentAccessFormatTests(testCtx, gr, true);
1838 
1839     /* Add the D/S tests */
1840     tcu::TestCaseGroup *depth_gr   = new tcu::TestCaseGroup(testCtx, "depth");
1841     tcu::TestCaseGroup *stencil_gr = new tcu::TestCaseGroup(testCtx, "stencil");
1842     string name_prefix             = "";
1843     string desc_prefix             = "Tests with ";
1844     createRasterizationOrderAttachmentAccessTestVariations(testCtx, depth_gr, name_prefix, desc_prefix, 1, false, true,
1845                                                            false);
1846     createRasterizationOrderAttachmentAccessTestVariations(testCtx, stencil_gr, name_prefix, desc_prefix, 1, false,
1847                                                            false, true);
1848     gr->addChild(depth_gr);
1849     gr->addChild(stencil_gr);
1850 
1851     return gr;
1852 }
1853 
1854 } // namespace rasterization
1855 } // namespace vkt
1856