xref: /aosp_15_r20/external/deqp/external/vulkancts/modules/vulkan/rasterization/vktShaderTileImageTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2022 The Khronos Group Inc.
6  * Copyright (c) 2022 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_EXT_shader_tile_image tests.
23  *//*--------------------------------------------------------------------*/
24 
25 // Draw overwrapped patches with incremental value. The last value should be the patch count.
26 // Decision is made with comparing between simulated value and result value.
27 // All multi sample tests run with per sample shading property except MsaaSampleMask test case.
28 // There are several variants.
29 //  - Color
30 //  - Depth
31 //  - Stencil
32 //  - Msaa
33 //  - Formats
34 //  - Draw Count
35 //  - Patch Count per Draw
36 //  - Coherent Mode
37 //  ...
38 
39 #include "vktShaderTileImageTests.hpp"
40 #include "deDefs.hpp"
41 #include "deSharedPtr.hpp"
42 #include "deUniquePtr.hpp"
43 #include "draw/vktDrawBufferObjectUtil.hpp"
44 #include "tcuCommandLine.hpp"
45 #include "tcuImageCompare.hpp"
46 #include "tcuResource.hpp"
47 #include "tcuStringTemplate.hpp"
48 #include "tcuTestLog.hpp"
49 #include "tcuTextureUtil.hpp"
50 #include "vkBuilderUtil.hpp"
51 #include "vkCmdUtil.hpp"
52 #include "vkDefs.hpp"
53 #include "vkImageUtil.hpp"
54 #include "vkMemUtil.hpp"
55 #include "vkObjUtil.hpp"
56 #include "vkPrograms.hpp"
57 #include "vkQueryUtil.hpp"
58 #include "vkRef.hpp"
59 #include "vkRefUtil.hpp"
60 #include "vkTypeUtil.hpp"
61 #include "vktRasterizationTests.hpp"
62 #include "vktTestCase.hpp"
63 
64 using namespace vk;
65 using de::MovePtr;
66 using de::SharedPtr;
67 
68 namespace vkt
69 {
70 
71 namespace rasterization
72 {
73 
74 namespace
75 {
76 
77 constexpr uint32_t kImageSize              = 4; // power of 2 for helper test
78 constexpr uint32_t kMultiDrawElementCount  = 3;
79 constexpr uint32_t kMultiPatchElementCount = 3;
80 constexpr uint32_t kMRTCount               = 2;
81 constexpr uint32_t kDerivative0            = 1; // derivative 0 + offset 1
82 constexpr uint32_t kDerivative1            = 2; // derivative 1 + offset 1
83 
84 enum class TestType
85 {
86     Color,
87     MultiRenderTarget,
88     MultiRenderTargetDynamicIndex,
89     MsaaSampleMask,
90     HelperClassColor,
91     HelperClassDepth,
92     HelperClassStencil,
93     Depth,
94     Stencil
95 };
96 
97 struct TestParam
98 {
99     bool coherent;
100     TestType testType;
101     VkFormat colorFormat;
102     VkFormat depthStencilFormat;
103     VkSampleCountFlagBits m_sampleCount;
104     bool multipleDrawCalls;
105     bool multiplePatchesPerDraw;
106     uint32_t frameBufferSize;
107 };
108 
isHelperClassTest(TestType testType)109 bool isHelperClassTest(TestType testType)
110 {
111     const bool helperClass = (testType == TestType::HelperClassColor) || (testType == TestType::HelperClassDepth) ||
112                              (testType == TestType::HelperClassStencil);
113     return helperClass;
114 }
115 
getSampleCount(VkSampleCountFlagBits sampleCount)116 uint32_t getSampleCount(VkSampleCountFlagBits sampleCount)
117 {
118     uint32_t ret = 0;
119     switch (sampleCount)
120     {
121     case VK_SAMPLE_COUNT_1_BIT:
122         ret = 1;
123         break;
124     case VK_SAMPLE_COUNT_2_BIT:
125         ret = 2;
126         break;
127     case VK_SAMPLE_COUNT_4_BIT:
128         ret = 4;
129         break;
130     case VK_SAMPLE_COUNT_8_BIT:
131         ret = 8;
132         break;
133     case VK_SAMPLE_COUNT_16_BIT:
134         ret = 16;
135         break;
136     case VK_SAMPLE_COUNT_32_BIT:
137         ret = 32;
138         break;
139     case VK_SAMPLE_COUNT_64_BIT:
140         ret = 64;
141         break;
142     default:
143         DE_ASSERT(false);
144     };
145     return ret;
146 }
147 
getSampleMask(TestType testType)148 uint32_t getSampleMask(TestType testType)
149 {
150     return (testType == TestType::MsaaSampleMask) ? 0xaaaaaaaa : 0;
151 }
152 
getColorAttachmentCount(TestType testType)153 uint32_t getColorAttachmentCount(TestType testType)
154 {
155     switch (testType)
156     {
157     case TestType::MultiRenderTargetDynamicIndex:
158     case TestType::MultiRenderTarget:
159     case TestType::HelperClassColor:
160     case TestType::HelperClassDepth:
161     case TestType::HelperClassStencil:
162         return kMRTCount;
163     default:
164         return 1;
165     }
166     return 1;
167 }
168 
getVertexCountPerPatch(const TestParam * testParam)169 uint32_t getVertexCountPerPatch(const TestParam *testParam)
170 {
171     return (testParam->testType == TestType::MsaaSampleMask) ? 3 : 6;
172 }
173 
getPatchesPerDrawCount(bool multiplePatchesPerDraw)174 uint32_t getPatchesPerDrawCount(bool multiplePatchesPerDraw)
175 {
176     return multiplePatchesPerDraw ? kMultiPatchElementCount : 1;
177 }
178 
getDrawCallCount(const TestParam * testParam)179 uint32_t getDrawCallCount(const TestParam *testParam)
180 {
181     if (isHelperClassTest(testParam->testType))
182     {
183         // helper class use two draw calls, but it is similar to single draw call
184         DE_ASSERT(!testParam->multipleDrawCalls);
185         return 2;
186     }
187 
188     return testParam->multipleDrawCalls ? kMultiDrawElementCount : 1;
189 }
190 
isNormalizedColorFormat(VkFormat format)191 bool isNormalizedColorFormat(VkFormat format)
192 {
193     const tcu::TextureFormat colorFormat(mapVkFormat(format));
194     const tcu::TextureChannelClass channelClass(tcu::getTextureChannelClass(colorFormat.type));
195     const bool normalizedColorFormat = (channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT ||
196                                         channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT);
197     return normalizedColorFormat;
198 }
199 
addOverhead(std::stringstream & shaderStream)200 void addOverhead(std::stringstream &shaderStream)
201 {
202     shaderStream << "{\n"
203                  << "    uint overheadLoop = uint(gl_FragCoord.x) * uint(${TOTAL_PATCH_COUNT} + 1);\n"
204                  << "    zero = patchIndex / (${TOTAL_PATCH_COUNT} + 1);\n"
205                  << "    for(uint index = 0u; index < overheadLoop; index++)\n"
206                  << "    {\n"
207                  << "        zero = uint(sin(float(zero)));\n"
208                  << "    }\n"
209                  << "}\n";
210 }
211 
transition2DImage(const vk::DeviceInterface & vk,vk::VkCommandBuffer cmdBuffer,vk::VkImage image,vk::VkImageAspectFlags aspectMask,vk::VkImageLayout oldLayout,vk::VkImageLayout newLayout,vk::VkAccessFlags srcAccessMask,vk::VkAccessFlags dstAccessMask,vk::VkPipelineStageFlags srcStageMask,vk::VkPipelineStageFlags dstStageMask)212 void transition2DImage(const vk::DeviceInterface &vk, vk::VkCommandBuffer cmdBuffer, vk::VkImage image,
213                        vk::VkImageAspectFlags aspectMask, vk::VkImageLayout oldLayout, vk::VkImageLayout newLayout,
214                        vk::VkAccessFlags srcAccessMask, vk::VkAccessFlags dstAccessMask,
215                        vk::VkPipelineStageFlags srcStageMask, vk::VkPipelineStageFlags dstStageMask)
216 {
217     vk::VkImageMemoryBarrier barrier;
218     barrier.sType                           = vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
219     barrier.pNext                           = DE_NULL;
220     barrier.srcAccessMask                   = srcAccessMask;
221     barrier.dstAccessMask                   = dstAccessMask;
222     barrier.oldLayout                       = oldLayout;
223     barrier.newLayout                       = newLayout;
224     barrier.srcQueueFamilyIndex             = VK_QUEUE_FAMILY_IGNORED;
225     barrier.dstQueueFamilyIndex             = VK_QUEUE_FAMILY_IGNORED;
226     barrier.image                           = image;
227     barrier.subresourceRange.aspectMask     = aspectMask;
228     barrier.subresourceRange.baseMipLevel   = 0;
229     barrier.subresourceRange.levelCount     = 1;
230     barrier.subresourceRange.baseArrayLayer = 0;
231     barrier.subresourceRange.layerCount     = 1;
232 
233     vk.cmdPipelineBarrier(cmdBuffer, srcStageMask, dstStageMask, (vk::VkDependencyFlags)0, 0,
234                           (const vk::VkMemoryBarrier *)DE_NULL, 0, (const vk::VkBufferMemoryBarrier *)DE_NULL, 1,
235                           &barrier);
236 }
237 
238 class ShaderTileImageTestCase : public TestCase
239 {
240 public:
241     ShaderTileImageTestCase(tcu::TestContext &context, const std::string &name, const TestParam &testParam);
242     ~ShaderTileImageTestCase() override = default;
243     TestInstance *createInstance(Context &context) const override;
244 
245 protected:
246     void initPrograms(SourceCollections &programCollection) const override;
247     void checkSupport(Context &context) const override;
248 
249     void addVS(SourceCollections &programCollection, const std::map<std::string, std::string> &params) const;
250     void addFS(SourceCollections &programCollection, const std::map<std::string, std::string> &params) const;
251     void addCS(SourceCollections &programCollection, const std::map<std::string, std::string> &params) const;
252 
253     void getColorTestTypeFS(std::stringstream &fragShader) const;
254     void getHelperClassTestTypeFS(std::stringstream &fragShader) const;
255     void getSampleMaskTypeFS(std::stringstream &fragShader) const;
256     void getDepthTestTypeFS(std::stringstream &fragShader) const;
257     void getStencilTestTypeFS(std::stringstream &fragShader) const;
258 
259 protected:
260     const TestParam m_testParam;
261 };
262 
263 class ShaderTileImageTestInstance : public TestInstance
264 {
265 public:
266     ShaderTileImageTestInstance(Context &context, const TestParam *testParam);
267     ~ShaderTileImageTestInstance() override = default;
268     tcu::TestStatus iterate() override;
269 
270 protected:
271     void initialize();
272     void generateCmdBuffer();
273     void generateVertexBuffer();
274     void generateAttachments();
275     Move<VkPipeline> generateGraphicsPipeline(bool disableColor0Write, bool disableDepthWrite,
276                                               bool disableStencilWrite);
277     void generateComputePipeline();
278     void rendering();
279     uint32_t getResultValue(uint32_t fx, uint32_t fy, uint32_t fs, uint32_t renderTargetID) const;
280     uint32_t simulate(uint32_t fx, uint32_t fy, uint32_t fs, uint32_t renderTargetID) const;
281     tcu::TestStatus checkResult() const;
282 
283 protected:
284     const TestParam *m_testParam;
285 
286     const DeviceInterface &m_vk;
287     SharedPtr<Draw::Buffer> m_vertexBuffer;
288 
289     Move<VkCommandPool> m_cmdPool;
290     Move<VkCommandBuffer> m_cmdBuffer;
291     Move<vk::VkDescriptorPool> m_descriptorPool;
292     Move<vk::VkDescriptorSet> m_descriptorSets[kMRTCount];
293     Move<VkPipelineLayout> m_graphicsPipelineLayout;
294     Move<VkPipeline> m_graphicsPipeline;
295     Move<VkPipeline> m_graphicsPipelineForHelperClass;
296     Move<vk::VkDescriptorSetLayout> m_computeDescriptorSetLayout;
297     Move<VkPipelineLayout> m_computePipelineLayout;
298     Move<VkPipeline> m_computePipeline;
299     Move<VkShaderModule> m_vertexModule;
300     Move<VkShaderModule> m_fragmentModule;
301     Move<VkImage> m_imageColor[kMRTCount];
302     MovePtr<Allocation> m_imageColorAlloc[kMRTCount];
303     uint32_t *m_imageColorBufferHostPtr;
304     Move<VkImageView> m_imageColorView[kMRTCount];
305     SharedPtr<Draw::Buffer> m_imageBuffer[kMRTCount];
306     Move<VkImage> m_imageDepthStencil;
307     MovePtr<Allocation> m_imageDepthStencilAlloc;
308     Move<VkImageView> m_imageDepthStencilView;
309 };
310 
ShaderTileImageTestCase(tcu::TestContext & context,const std::string & name,const TestParam & testParam)311 ShaderTileImageTestCase::ShaderTileImageTestCase(tcu::TestContext &context, const std::string &name,
312                                                  const TestParam &testParam)
313     : TestCase(context, name)
314     , m_testParam(testParam)
315 {
316 }
317 
addVS(SourceCollections & programCollection,const std::map<std::string,std::string> & params) const318 void ShaderTileImageTestCase::addVS(SourceCollections &programCollection,
319                                     const std::map<std::string, std::string> &params) const
320 {
321     std::stringstream vertShader;
322     vertShader << "#version 450 core\n"
323                << "precision highp float;\n"
324                << "precision highp int;\n"
325                << "layout(location = 0) in highp vec2 v_position;\n"
326                << "layout(location = 0) flat out uint patchIndex;"
327                << "layout( push_constant ) uniform ConstBlock\n"
328                << "{\n"
329                << "    highp uint drawIndex;\n"
330                << "};\n"
331                << "void main ()\n"
332                << "{\n"
333                << "    uint localPatchIndex = uint(gl_VertexIndex) / ${VERTEX_COUNT_PER_PATCH} + 1;\n" // index from 1
334                << "    uint patchCountPerDraw = ${PATCH_COUNT_PER_DRAW};\n"
335                << "    uint globalPatchIndex = drawIndex * patchCountPerDraw + localPatchIndex;\n"
336                << "    patchIndex = globalPatchIndex;\n"
337                << "    gl_Position = vec4(v_position, ${INV_TOTAL_PATCH_COUNT} * globalPatchIndex, 1);\n"
338                << "}\n";
339 
340     tcu::StringTemplate vertShaderTpl(vertShader.str());
341     programCollection.glslSources.add("vert") << glu::VertexSource(vertShaderTpl.specialize(params));
342 }
343 
getColorTestTypeFS(std::stringstream & fragShader) const344 void ShaderTileImageTestCase::getColorTestTypeFS(std::stringstream &fragShader) const
345 {
346     const uint32_t attachmentCount     = getColorAttachmentCount(m_testParam.testType);
347     const bool mrtDynamicIndexTestType = (m_testParam.testType == TestType::MultiRenderTargetDynamicIndex);
348     const bool multiSampleTest         = (m_testParam.m_sampleCount != VK_SAMPLE_COUNT_1_BIT);
349 
350     const tcu::TextureFormat colorFormat(mapVkFormat(m_testParam.colorFormat));
351     const tcu::TextureChannelClass channelClass(tcu::getTextureChannelClass(colorFormat.type));
352     const bool normalizedColorFormat = isNormalizedColorFormat(m_testParam.colorFormat);
353     const tcu::IVec4 channelBitDepth = tcu::getTextureFormatBitDepth(colorFormat);
354 
355     fragShader << "#version 450 core\n"
356                << "#extension GL_EXT_shader_tile_image : require\n"
357                << "precision highp float;\n"
358                << "precision highp int;\n"
359                << "layout( push_constant ) uniform ConstBlock\n"
360                << "{\n"
361                << "    highp uint drawIndex;\n"
362                << "};\n"
363                << "layout( location = 0 ) flat in uint patchIndex;\n";
364 
365     if (!m_testParam.coherent)
366     {
367         fragShader << "layout( non_coherent_color_attachment_readEXT ) in;\n";
368     }
369 
370     if (mrtDynamicIndexTestType)
371     {
372         // layout( location = 0 ) tileImageEXT highp attachmentEXT colorIn[0]
373         fragShader << "layout( location = 0 ) tileImageEXT highp ${TILE_IMAGE_TYPE} colorIn[${ATTACHMENT_COUNT}];\n";
374     }
375     else
376     {
377         for (uint32_t i = 0; i < attachmentCount; i++)
378         {
379             // layout( location = 0 ) tileImageEXT highp attachmentEXT colorIn0
380             fragShader << "layout( location = " << i << ") tileImageEXT highp ${TILE_IMAGE_TYPE} colorIn" << i << ";\n";
381         }
382     }
383 
384     for (uint32_t i = 0; i < attachmentCount; i++)
385     {
386         // layout( location = 0 ) out highp vec4 out0
387         fragShader << "layout( location = " << i << " ) out highp ${OUTPUT_VECTOR_NAME} out" << i << ";\n";
388     }
389 
390     fragShader << "void main()\n"
391                << "{\n"
392                << "    uint zero = 0;\n"
393                << "    uvec2 previous[${ATTACHMENT_COUNT}];\n";
394 
395     float amplifier = 1.0f;
396     if (normalizedColorFormat)
397     {
398         amplifier = (channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT) ?
399                         static_cast<float>(1 << (channelBitDepth.y() - 1)) : // signed
400                         static_cast<float>((1 << channelBitDepth.y()) - 1);  // unsigned
401 
402         // color output precision is less than test case;
403         DE_ASSERT(amplifier > static_cast<float>(kMultiPatchElementCount * kMultiDrawElementCount * attachmentCount +
404                                                  getSampleCount(m_testParam.m_sampleCount)));
405     }
406 
407     for (uint32_t i = 0; i < attachmentCount; i++)
408     {
409         // in0 or colorIn[0]
410         const std::string inputImage =
411             mrtDynamicIndexTestType ? "colorIn[" + std::to_string(i) + "]" : "colorIn" + std::to_string(i);
412 
413         // (in0) or (colorIn0, gl_SampleID)
414         const std::string funcParams = multiSampleTest ? "(" + inputImage + ", gl_SampleID)" : "(" + inputImage + ")";
415 
416         if (normalizedColorFormat)
417         {
418             // previous[0] = round(colorAttachmentRead(in0) *  amplifier).xy;\n";
419             fragShader << "    previous[" << i << "] = uvec2(round((colorAttachmentReadEXT" << funcParams << " * "
420                        << amplifier << ").xy));\n";
421         }
422         else
423         {
424             // previous[0] *= uvec2(round(colorAttachmentRead(in0).xy));\n";
425             fragShader << "    previous[" << i << "] = uvec2(round((colorAttachmentReadEXT" << funcParams
426                        << ").xy));\n";
427         }
428     }
429 
430     // add overhead after fetching data
431     addOverhead(fragShader);
432 
433     // used only for normalized color format
434     const float invAmplifier = 1.0f / static_cast<float>(amplifier);
435 
436     // write output
437     for (uint32_t i = 0; i < attachmentCount; i++)
438     {
439         // if (previous[0].x == 0 && patchIndex == 1)", initial write
440         //  out0.y = float(patchIndex + zero + gl_SampleID +  0);"
441         // else if (previous[0].x == 0 && (previous[0].y + 1) == (patchIndex + gl_SampleID + 0))"
442         //  out0.y = float(previous[0].y + 1);"
443         // else
444         //  out0.y = float(previous[0].y);"
445         //  out0.x = 1;" // error
446         fragShader << "    if (previous[" << i << "].x == 0 && patchIndex == 1)\n"
447                    << "    {\n"
448                    << "        out" << i << ".y = ${OUTPUT_BASIC_TYPE}(patchIndex + zero + gl_SampleID + " << i
449                    << ");\n"
450                    << "    }\n"
451                    << "    else if (previous[" << i << "].x == 0 && (previous[" << i
452                    << "].y + 1) == (patchIndex + gl_SampleID + " << i << "))\n"
453                    << "    {\n"
454                    << "        out" << i << ".y = ${OUTPUT_BASIC_TYPE}(previous[" << i << "].y + 1 + zero);\n"
455                    << "    }\n"
456                    << "    else\n"
457                    << "    {\n"
458                    << "        out" << i << ".y = ${OUTPUT_BASIC_TYPE}(previous[" << i << "].y);\n" // for debug purpose
459                    << "        out" << i << ".x = 1;\n"                                             // error
460                    << "    }\n";
461 
462         if (normalizedColorFormat)
463         {
464             // out0.y *= invAmplifier;
465             fragShader << "        out" << i << ".y *= " << invAmplifier << ";\n";
466         }
467     }
468     fragShader << "}\n";
469 }
470 
getHelperClassTestTypeFS(std::stringstream & fragShader) const471 void ShaderTileImageTestCase::getHelperClassTestTypeFS(std::stringstream &fragShader) const
472 {
473     const bool depthHelperClassTest   = (m_testParam.testType == TestType::HelperClassDepth);
474     const bool stencilHelperClassTest = (m_testParam.testType == TestType::HelperClassStencil);
475 
476     DE_ASSERT(getPatchesPerDrawCount(!m_testParam.multiplePatchesPerDraw));
477     DE_ASSERT(getDrawCallCount(&m_testParam) == 2);
478     DE_ASSERT(getColorAttachmentCount(m_testParam.testType) == 2);
479     DE_ASSERT((m_testParam.m_sampleCount == VK_SAMPLE_COUNT_1_BIT));
480     DE_ASSERT(!isNormalizedColorFormat(m_testParam.colorFormat));
481 
482     fragShader << "#version 450 core\n"
483                << "#extension GL_EXT_shader_tile_image : require\n"
484                << "precision highp float;\n"
485                << "precision highp int;\n"
486                << "layout( push_constant ) uniform ConstBlock\n"
487                << "{\n"
488                << "    highp uint drawIndex;\n"
489                << "};\n"
490                << "layout( location = 0 ) flat in uint patchIndex;\n";
491 
492     if (!m_testParam.coherent)
493     {
494         fragShader << "layout( non_coherent_color_attachment_readEXT ) in;\n";
495         if (depthHelperClassTest)
496         {
497             fragShader << "layout( non_coherent_depth_attachment_readEXT ) in;\n";
498         }
499 
500         if (stencilHelperClassTest)
501         {
502             fragShader << "layout( non_coherent_stencil_attachment_readEXT ) in;\n";
503         }
504     }
505 
506     fragShader << "layout(location = 0) tileImageEXT highp ${TILE_IMAGE_TYPE} colorIn0;\n";
507     fragShader << "layout(location = 1) tileImageEXT highp ${TILE_IMAGE_TYPE} colorIn1;\n";
508 
509     fragShader << "layout(location = 0) out highp ${OUTPUT_VECTOR_NAME} out0;\n";
510     fragShader << "layout(location = 1) out highp ${OUTPUT_VECTOR_NAME} out1;\n";
511 
512     fragShader << "void main()\n"
513                << "{\n"
514                << "    uint zero = 0;\n"
515                << "    uvec2 previous;\n";
516 
517     if (depthHelperClassTest)
518     {
519         fragShader << " uint scalingFactor = ${TOTAL_PATCH_COUNT};\n";
520         fragShader << "    previous.x = uint(round(colorAttachmentReadEXT(colorIn0).x));\n";       // read error status
521         fragShader << "    previous.y = uint(round(depthAttachmentReadEXT() * scalingFactor));\n"; // read depth value
522     }
523     else if (stencilHelperClassTest)
524     {
525         fragShader << "    previous.x = uint(round(colorAttachmentReadEXT(colorIn0).x));\n"; // read error status
526         fragShader << "    previous.y = uint(stencilAttachmentReadEXT());\n";                // read stencil value
527     }
528     else
529     {
530         fragShader << "    previous = uvec2(round((colorAttachmentReadEXT(colorIn0)).xy));\n";
531     }
532 
533     {
534         // draw only one triangle for helperClassTestType, dx or dy should be 0 inside of triangle.
535         // And they should be patchIndex in the diagonal edge of triangle.
536         fragShader << "    uint err = 0;\n"
537                    << "    uint dx = 0;\n"
538                    << "    uint dy = 0;\n"
539                    << "    if (patchIndex != 1)"
540                    << "    {\n"
541                    << "        dx = uint(round(abs(dFdxFine(previous.y))));\n"
542                    << "        dy = uint(round(abs(dFdyFine(previous.y))));\n"
543                    << "        uint err = 0;\n"
544                    << "        if ((dx != 0 && dx != patchIndex - 1) || (dy != 0 && dy != patchIndex - 1))\n"
545                    << "        {\n"
546                    << "            err = 1;\n" // first draw doesn't have error check.
547                    << "        }\n"
548                    << "    }\n";
549     }
550 
551     // add overhead after fetching data
552     addOverhead(fragShader);
553 
554     // first draw writes to attachment0
555     // second draw reads from attachment0(depth) writes to attachment1
556     {
557         fragShader
558             << "    if (patchIndex == 1 && err != 1)\n"
559             << "    {\n"
560             << "        out0.y = ${OUTPUT_BASIC_TYPE}(patchIndex);\n"
561             << "        out0.x = 0;\n" // error
562             << "    }\n"
563             << "    else if (previous.x == 0 && err != 1 && ((previous.y + 1) == patchIndex || previous.y == 0))\n"
564             << "    {\n"
565             << "        out1.y = ${OUTPUT_BASIC_TYPE}(max(dx, dy) + 1);\n" // last 1 is to differentiate clear value
566             << "    }\n"
567             << "    else\n"
568             << "    {\n"
569             << "        out0.y = ${OUTPUT_BASIC_TYPE}(previous.y);\n" // for debug purpose
570             << "        out0.x = 1;\n"                                // error
571             << "        out1.y = ${OUTPUT_BASIC_TYPE}(previous.x);\n"
572             << "        out1.x = 1;\n" // error
573             << "    }\n";
574     }
575     fragShader << "}\n";
576 }
577 
getSampleMaskTypeFS(std::stringstream & fragShader) const578 void ShaderTileImageTestCase::getSampleMaskTypeFS(std::stringstream &fragShader) const
579 {
580     const uint32_t sampleCount = getSampleCount(m_testParam.m_sampleCount);
581 
582     const tcu::TextureFormat colorFormat(mapVkFormat(m_testParam.colorFormat));
583     const tcu::TextureChannelClass channelClass(tcu::getTextureChannelClass(colorFormat.type));
584     const bool normalizedColorFormat = isNormalizedColorFormat(m_testParam.colorFormat);
585     const tcu::IVec4 channelBitDepth = tcu::getTextureFormatBitDepth(colorFormat);
586 
587     uint32_t amplifier = 1;
588     if (normalizedColorFormat)
589     {
590         amplifier = (channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT) ?
591                         (1 << (channelBitDepth.y() - 1)) : // signed
592                         ((1 << channelBitDepth.y()) - 1);  // unsigned
593     }
594 
595     // Samples which is not covered should be 0
596     fragShader << "#version 450 core\n"
597                << "#extension GL_EXT_shader_tile_image : require\n"
598                << "precision highp float;\n"
599                << "precision highp int;\n"
600                << "layout( push_constant ) uniform ConstBlock\n"
601                << "{\n"
602                << "    highp uint drawIndex;\n"
603                << "};\n";
604     if (!m_testParam.coherent)
605     {
606         fragShader << "layout( non_coherent_color_attachment_readEXT ) in;\n";
607     }
608     fragShader << "layout( location = 0 ) flat in uint patchIndex;\n"
609                << "layout( location = 0 ) tileImageEXT highp ${TILE_IMAGE_TYPE} colorIn0;\n"
610                << "layout( location = 0 ) out highp ${OUTPUT_VECTOR_NAME} out0;\n"
611                << "\n"
612                << "void main()\n"
613                << "{\n"
614                << "    uint zero = 0;\n"
615                << "    uint previous = 0;\n"
616                << "    bool error = false;\n"
617                << "    for (int i = 0; i < " << sampleCount << "; ++i)\n"
618                << "    {\n"
619                << "        if (((gl_SampleMaskIn[0] >> i) & 0x1) == 0x1)\n"
620                << "        {\n"
621                << "            uvec2 previousSample = uvec2(round(colorAttachmentReadEXT"
622                << "(colorIn0, i) * " << amplifier << ")).xy;\n"
623                << "            if (previousSample.x != 0)\n"
624                << "            {\n"
625                << "                error = true;\n"
626                << "                break;"
627                << "            }\n"
628                << "            if (previous == 0)\n"
629                << "            {\n"
630                << "                previous = previousSample.y;\n" // write non zero value to the covered sample
631                << "            }\n"
632                << "\n"
633                << "            if ((patchIndex != 1 && previousSample.y == 0) || previous != previousSample.y)\n"
634                << "            {\n"
635                << "                error = true;\n"
636                << "                break;\n"
637                << "            }\n"
638                << "        }\n"
639                << "    }\n"
640                << "\n";
641 
642     // add overhead after fetching data
643     addOverhead(fragShader);
644 
645     // write output
646     fragShader << "if (!error && (previous + 1 == patchIndex))\n"
647                << "    {\n"
648                << "        out0.y = ${OUTPUT_BASIC_TYPE}(previous + 1 + zero);\n"
649                << "    }\n"
650                << "    else\n"
651                << "    {\n"
652                << "        out0.y = ${OUTPUT_BASIC_TYPE}(previous);\n"
653                << "        out0.x = 1;\n" // error
654                << "    }\n";
655 
656     const float invAmplifier = 1.0f / static_cast<float>(amplifier);
657     if (normalizedColorFormat)
658     {
659         fragShader << "        out0.y *= " << invAmplifier << ";\n";
660     }
661 
662     fragShader << "}\n";
663 }
664 
getDepthTestTypeFS(std::stringstream & fragShader) const665 void ShaderTileImageTestCase::getDepthTestTypeFS(std::stringstream &fragShader) const
666 {
667     const bool multiSampleTest        = (m_testParam.m_sampleCount != VK_SAMPLE_COUNT_1_BIT);
668     const std::string depthFuncParams = multiSampleTest ? "(gl_SampleID)" : "()";
669     const std::string colorFuncParams = multiSampleTest ? "(colorIn0, gl_SampleID)" : "(colorIn0)";
670     const uint32_t sampleCount        = getSampleCount(m_testParam.m_sampleCount);
671 
672     fragShader << "#version 450 core\n"
673                << "#extension GL_EXT_shader_tile_image : require\n"
674                << "precision highp float;\n"
675                << "precision highp int;\n"
676                << "layout( push_constant ) uniform ConstBlock\n"
677                << "{\n"
678                << "    highp uint drawIndex;\n"
679                << "};\n";
680     if (!m_testParam.coherent)
681     {
682         fragShader << "layout( non_coherent_depth_attachment_readEXT ) in;\n";
683         fragShader << "layout( non_coherent_color_attachment_readEXT ) in;\n";
684     }
685     fragShader << "layout( location = 0 ) flat in uint patchIndex;\n"
686                << "layout( location = 0 ) tileImageEXT highp ${TILE_IMAGE_TYPE} colorIn0;\n"
687                << "layout( location = 0 ) out highp ${OUTPUT_VECTOR_NAME} out0;\n"
688                << "\n"
689                << "void main()\n"
690                << "{\n"
691                << "    uint zero = 0;\n"
692                << " uint scalingFactor = ${TOTAL_PATCH_COUNT};\n";
693     if (multiSampleTest)
694     {
695         // scaling with (patch count + sample count) for multisample case
696         fragShader << " scalingFactor += " << sampleCount << ";\n";
697     }
698     fragShader << "    uint previousDepth = uint(round(depthAttachmentReadEXT" << depthFuncParams
699                << " * scalingFactor));\n"
700                << "    ${OUTPUT_VECTOR_NAME} previous = ${OUTPUT_VECTOR_NAME}(round(colorAttachmentReadEXT"
701                << colorFuncParams << "));\n";
702 
703     // add overhead after fetching data
704     addOverhead(fragShader);
705 
706     // write output
707     fragShader
708         << "    if (previous.x == 0 && patchIndex == 1)\n"
709         << "    {\n"
710         << "        out0.y = (1u + zero + gl_SampleID);\n"
711         << "    }\n"
712         << "    else if (previous.x == 0 && (previous.y + 1) == (patchIndex + gl_SampleID) && (previousDepth + 1) "
713            "== (patchIndex + gl_SampleID))\n"
714         << "    {\n"
715         << "        out0.y = ${OUTPUT_BASIC_TYPE}(previousDepth + 1 + zero);\n"
716         << "    }\n"
717         << "    else\n"
718         << "    {\n"
719         << "        out0.y = ${OUTPUT_BASIC_TYPE}(previousDepth);\n" // debug purpose
720         << "        out0.x = 1;\n"                                   // error
721         << "    }\n";
722 
723     if (multiSampleTest)
724     {
725         // Depth value is written without adding SampleID.
726         // Forcely write all fragment depth
727         fragShader << " gl_FragDepth = float(out0.y) / scalingFactor;\n";
728     }
729 
730     fragShader << "}\n";
731 }
732 
getStencilTestTypeFS(std::stringstream & fragShader) const733 void ShaderTileImageTestCase::getStencilTestTypeFS(std::stringstream &fragShader) const
734 {
735     const bool multiSampleTest          = (m_testParam.m_sampleCount != VK_SAMPLE_COUNT_1_BIT);
736     const std::string stencilFuncParams = multiSampleTest ? "(gl_SampleID)" : "()";
737     const std::string colorFuncParams   = multiSampleTest ? "(colorIn0, gl_SampleID)" : "(colorIn0)";
738 
739     fragShader << "#version 450 core\n"
740                << "#extension GL_EXT_shader_tile_image : require\n"
741                << "precision highp float;\n"
742                << "precision highp int;\n"
743                << "layout( push_constant ) uniform ConstBlock\n"
744                << "{\n"
745                << "    highp uint drawIndex;\n"
746                << "};\n";
747     if (!m_testParam.coherent)
748     {
749         fragShader << "layout( non_coherent_stencil_attachment_readEXT ) in;\n";
750         fragShader << "layout( non_coherent_color_attachment_readEXT ) in;\n";
751     }
752     fragShader << "layout( location = 0 ) flat in uint patchIndex;\n"
753                << "layout( location = 0 ) tileImageEXT highp ${TILE_IMAGE_TYPE} colorIn0;\n"
754                << "layout( location = 0 ) out highp ${OUTPUT_VECTOR_NAME} out0;\n"
755                << "\n"
756                << "void main()\n"
757                << "{\n"
758                << "    uint zero = 0;\n"
759                << "    uint previousStencil = uint(round(stencilAttachmentReadEXT" << stencilFuncParams << " ));\n"
760                << "    ${OUTPUT_VECTOR_NAME} previous = ${OUTPUT_VECTOR_NAME}(round(colorAttachmentReadEXT"
761                << colorFuncParams << "));\n";
762 
763     // add overhead after fetching data
764     addOverhead(fragShader);
765 
766     // write output
767     fragShader << "    if (previous.x == 0 && (previous.y + 1) == patchIndex && (previousStencil + 1) == patchIndex)\n"
768                << "    {\n"
769                << "        out0.y = ${OUTPUT_BASIC_TYPE}(previousStencil + 1 + zero);\n"
770                << "    }\n"
771                << "    else\n"
772                << "    {\n"
773                << "        out0.y = ${OUTPUT_BASIC_TYPE}(previousStencil);\n" // debug purpose
774                << "        out0.x = 1;\n"                                     // error
775                << "    }\n"
776                << "}\n";
777 }
778 
addFS(SourceCollections & programCollection,const std::map<std::string,std::string> & params) const779 void rasterization::ShaderTileImageTestCase::addFS(SourceCollections &programCollection,
780                                                    const std::map<std::string, std::string> &params) const
781 {
782     std::stringstream fragShader;
783 
784     switch (m_testParam.testType)
785     {
786     case TestType::Color:
787     case TestType::MultiRenderTarget:
788     case TestType::MultiRenderTargetDynamicIndex:
789         getColorTestTypeFS(fragShader);
790         break;
791     case TestType::HelperClassColor:
792     case TestType::HelperClassDepth:
793     case TestType::HelperClassStencil:
794         getHelperClassTestTypeFS(fragShader);
795         break;
796     case TestType::MsaaSampleMask:
797         getSampleMaskTypeFS(fragShader);
798         break;
799     case TestType::Depth:
800         getDepthTestTypeFS(fragShader);
801         break;
802     case TestType::Stencil:
803         getStencilTestTypeFS(fragShader);
804         break;
805     default:
806         DE_ASSERT(true);
807     }
808 
809     tcu::StringTemplate fragShaderTpl(fragShader.str());
810     programCollection.glslSources.add("frag") << glu::FragmentSource(fragShaderTpl.specialize(params));
811 }
812 
813 // Copy Image to Buffer using Compute Shader for handling multi sample cases
addCS(SourceCollections & programCollection,const std::map<std::string,std::string> & params) const814 void ShaderTileImageTestCase::addCS(SourceCollections &programCollection,
815                                     const std::map<std::string, std::string> &params) const
816 {
817     std::stringstream compShader;
818 
819     const uint32_t sampleCount = getSampleCount(m_testParam.m_sampleCount);
820     const std::string fsampler = sampleCount > 1 ? "texture2DMS" : "texture2D";
821     const std::string usampler = sampleCount > 1 ? "utexture2DMS" : "utexture2D";
822     const std::string isampler = sampleCount > 1 ? "itexture2DMS" : "itexture2D";
823 
824     const tcu::TextureFormat colorFormat(mapVkFormat(m_testParam.colorFormat));
825     const tcu::TextureChannelClass channelClass(tcu::getTextureChannelClass(colorFormat.type));
826     const tcu::IVec4 channelBitDepth = tcu::getTextureFormatBitDepth(colorFormat);
827     const bool normalizedColorFormat = isNormalizedColorFormat(m_testParam.colorFormat);
828 
829     std::string sampler;
830     switch (channelClass)
831     {
832     case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
833         sampler = usampler;
834         break;
835     case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
836         sampler = isampler;
837         break;
838     default:
839         sampler = fsampler;
840     }
841 
842     uint32_t amplifier = 1;
843 
844     if (normalizedColorFormat)
845     {
846         amplifier = (channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT) ?
847                         (1 << (channelBitDepth.y() - 1)) : // signed
848                         ((1 << channelBitDepth.y()) - 1);  // unsigned
849     }
850 
851     // Compute shader copies color to linear layout in buffer memory
852     compShader << "#version 450 core\n"
853                << "#extension GL_EXT_samplerless_texture_functions : enable\n"
854                << "precision highp float;\n"
855                << "precision highp int;\n"
856                << "layout(set = 0, binding = 0) uniform " << sampler << " colorTex;\n"
857                << "layout(set = 0, binding = 1, std430) buffer Block0 { uvec2 values[]; } colorbuf;\n"
858                << "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
859                << "void main()\n"
860                << "{\n"
861                << "    for (uint i = 0u; i < " << sampleCount << "u; ++i) {\n"
862                << "        uint idx = ((gl_GlobalInvocationID.y * " << m_testParam.frameBufferSize
863                << "u) + gl_GlobalInvocationID.x) * " << sampleCount << "u + i;\n";
864 
865     if (normalizedColorFormat)
866     {
867         compShader
868             << "        colorbuf.values[idx].y = uint(round(texelFetch(colorTex, ivec2(gl_GlobalInvocationID.xy), "
869                "int(i)).y * "
870             << amplifier << "));\n";
871         compShader
872             << "        colorbuf.values[idx].x = uint(round(texelFetch(colorTex, ivec2(gl_GlobalInvocationID.xy), "
873                "int(i)).x));\n";
874     }
875     else
876     {
877         compShader << "        colorbuf.values[idx] = uvec2(round(vec2(texelFetch(colorTex, "
878                       "ivec2(gl_GlobalInvocationID.xy), int(i)).xy)));\n";
879     }
880 
881     compShader << "    }\n"
882                << "}\n";
883 
884     tcu::StringTemplate computeShaderTpl(compShader.str());
885     programCollection.glslSources.add("comp") << glu::ComputeSource(computeShaderTpl.specialize(params));
886 }
887 
initPrograms(SourceCollections & programCollection) const888 void ShaderTileImageTestCase::initPrograms(SourceCollections &programCollection) const
889 {
890     std::map<std::string, std::string> params;
891 
892     const uint32_t drawCount         = getDrawCallCount(&m_testParam);
893     const uint32_t patchCountPerDraw = getPatchesPerDrawCount(m_testParam.multiplePatchesPerDraw);
894     const uint32_t attachmentCount   = getColorAttachmentCount(m_testParam.testType);
895     const tcu::TextureFormat colorFormat(mapVkFormat(m_testParam.colorFormat));
896     const tcu::TextureChannelClass channelClass(tcu::getTextureChannelClass(colorFormat.type));
897 
898     params["VERTEX_COUNT_PER_PATCH"] = std::to_string(getVertexCountPerPatch(&m_testParam));
899     params["PATCH_COUNT_PER_DRAW"]   = std::to_string(patchCountPerDraw);
900     params["INV_TOTAL_PATCH_COUNT"]  = std::to_string(1.0f / static_cast<float>(drawCount * patchCountPerDraw));
901     params["TOTAL_PATCH_COUNT"]      = std::to_string(drawCount * patchCountPerDraw);
902     params["ATTACHMENT_COUNT"]       = std::to_string(attachmentCount);
903 
904     std::string strVecName;
905     std::string strBasicType;
906     std::string strTileImageType;
907 
908     switch (channelClass)
909     {
910     case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
911         strVecName       = "uvec";
912         strTileImageType = "uattachmentEXT";
913         strBasicType     = "uint";
914         break;
915     case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
916         strVecName       = "ivec";
917         strTileImageType = "iattachmentEXT";
918         strBasicType     = "int";
919         break;
920     default:
921         strVecName       = "vec";
922         strTileImageType = "attachmentEXT";
923         strBasicType     = "float";
924     }
925     params["OUTPUT_VECTOR_NAME"] = strVecName + std::to_string(tcu::getNumUsedChannels(colorFormat.order));
926     params["OUTPUT_BASIC_TYPE"]  = strBasicType;
927     params["TILE_IMAGE_TYPE"]    = strTileImageType;
928 
929     addVS(programCollection, params);
930     addFS(programCollection, params);
931     addCS(programCollection, params);
932 }
933 
createInstance(Context & context) const934 TestInstance *ShaderTileImageTestCase::createInstance(Context &context) const
935 {
936     return new ShaderTileImageTestInstance(context, &m_testParam);
937 }
938 
checkSupport(Context & context) const939 void ShaderTileImageTestCase::checkSupport(Context &context) const
940 {
941     if (!context.requireDeviceFunctionality("VK_KHR_dynamic_rendering"))
942     {
943         TCU_THROW(NotSupportedError, "VK_KHR_dynamic_rendering not supported");
944     }
945 
946     if (!context.requireDeviceFunctionality("VK_EXT_shader_tile_image"))
947     {
948         TCU_THROW(NotSupportedError, "VK_EXT_shader_tile_image not supported");
949     }
950     /* sampleRateShading must be enabled to call fragment shader for all the samples in multisampling */
951     VkPhysicalDeviceShaderTileImageFeaturesEXT shaderTileImageFeature = {};
952     shaderTileImageFeature.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_TILE_IMAGE_FEATURES_EXT;
953 
954     VkPhysicalDeviceFeatures features   = {};
955     VkPhysicalDeviceFeatures2 features2 = {};
956     features2.sType                     = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
957     features2.pNext                     = &shaderTileImageFeature;
958 
959     context.getInstanceInterface().getPhysicalDeviceFeatures(context.getPhysicalDevice(), &features);
960     context.getInstanceInterface().getPhysicalDeviceFeatures2(context.getPhysicalDevice(), &features2);
961 
962     if (!shaderTileImageFeature.shaderTileImageColorReadAccess)
963     {
964         TCU_THROW(NotSupportedError, "color read access of VK_EXT_shader_tile_image is not supported");
965     }
966     switch (m_testParam.testType)
967     {
968     case TestType::Depth:
969     case TestType::HelperClassDepth:
970         if (!shaderTileImageFeature.shaderTileImageDepthReadAccess)
971         {
972             TCU_THROW(NotSupportedError, "depth read access of VK_EXT_shader_tile_image is not supported");
973         }
974         break;
975     case TestType::Stencil:
976     case TestType::HelperClassStencil:
977         if (!shaderTileImageFeature.shaderTileImageStencilReadAccess)
978         {
979             TCU_THROW(NotSupportedError, "stencil read access of VK_EXT_shader_tile_image is not supported");
980         }
981         break;
982     case TestType::Color:
983     case TestType::MultiRenderTarget:
984     case TestType::MultiRenderTargetDynamicIndex:
985     case TestType::MsaaSampleMask:
986     case TestType::HelperClassColor:
987         break;
988     default:
989         DE_ASSERT(0);
990     }
991 
992     VkPhysicalDeviceVulkan12Properties vulkan12Properties = {};
993     vulkan12Properties.sType                              = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_PROPERTIES;
994 
995     VkPhysicalDeviceShaderTileImagePropertiesEXT shaderTileImageProperties = {};
996     shaderTileImageProperties.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_TILE_IMAGE_PROPERTIES_EXT;
997     shaderTileImageProperties.pNext = &vulkan12Properties;
998 
999     VkPhysicalDeviceProperties2 properties = {};
1000     properties.sType                       = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
1001     properties.pNext                       = &shaderTileImageProperties;
1002 
1003     context.getInstanceInterface().getPhysicalDeviceProperties2(context.getPhysicalDevice(), &properties);
1004 
1005     // shaderTileImageReadSampleFromPixelRateInvocation is a boolean that will be VK_TRUE if reading from samples from a
1006     // pixel rate fragment invocation is supported when VkPipelineMultisampleStateCreateInfo::rasterizationSamples > 1.
1007     // shaderTileImageReadFromHelperInvocation is a boolean that will be VK_TRUE if reads of tile image data from helper
1008     // fragment invocations result in valid values.
1009     if (!shaderTileImageProperties.shaderTileImageReadSampleFromPixelRateInvocation)
1010     {
1011         if (m_testParam.testType == TestType::MsaaSampleMask)
1012         {
1013             TCU_THROW(NotSupportedError, "multi-samples pixel access of VK_EXT_shader_tile_image is not supported");
1014         }
1015     }
1016 
1017     if (!shaderTileImageProperties.shaderTileImageReadFromHelperInvocation)
1018     {
1019         if (isHelperClassTest(m_testParam.testType))
1020         {
1021             TCU_THROW(NotSupportedError, "helper class fragments access of VK_EXT_shader_tile_image is not supported");
1022         }
1023     }
1024 
1025     const tcu::TextureFormat colorFormat(mapVkFormat(m_testParam.colorFormat));
1026     const tcu::TextureChannelClass channelClass(tcu::getTextureChannelClass(colorFormat.type));
1027     if (channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER ||
1028         channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)
1029     {
1030         if ((vulkan12Properties.framebufferIntegerColorSampleCounts & m_testParam.m_sampleCount) == 0 ||
1031             (properties.properties.limits.sampledImageIntegerSampleCounts & m_testParam.m_sampleCount) == 0)
1032         {
1033             TCU_THROW(NotSupportedError, "Sample count not supported");
1034         }
1035     }
1036     else
1037     {
1038         if ((properties.properties.limits.framebufferColorSampleCounts & m_testParam.m_sampleCount) == 0 ||
1039             (properties.properties.limits.sampledImageColorSampleCounts & m_testParam.m_sampleCount) == 0)
1040         {
1041             TCU_THROW(NotSupportedError, "Sample count not supported");
1042         }
1043     }
1044 
1045     if (m_testParam.m_sampleCount != VK_SAMPLE_COUNT_1_BIT && m_testParam.testType != TestType::MsaaSampleMask &&
1046         !features.sampleRateShading)
1047     {
1048         TCU_THROW(NotSupportedError, "sampleRateShading feature not supported");
1049     }
1050 
1051     const uint32_t attachmentCount = getColorAttachmentCount(m_testParam.testType);
1052 
1053     if (properties.properties.limits.maxFragmentOutputAttachments < attachmentCount ||
1054         properties.properties.limits.maxPerStageDescriptorInputAttachments < attachmentCount)
1055     {
1056         TCU_THROW(NotSupportedError, "attachment number not supported");
1057     }
1058 
1059     const InstanceInterface &vki    = context.getInstanceInterface();
1060     VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
1061     const VkFormatProperties colorFormatProperties(
1062         getPhysicalDeviceFormatProperties(vki, physicalDevice, m_testParam.colorFormat));
1063     const VkFormatProperties dsFormatProperties(
1064         getPhysicalDeviceFormatProperties(vki, physicalDevice, m_testParam.depthStencilFormat));
1065 
1066     if ((colorFormatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) == 0)
1067     {
1068         TCU_THROW(NotSupportedError, "Format can't be used as color attachment");
1069     }
1070 
1071     if ((dsFormatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) == 0)
1072     {
1073         TCU_THROW(NotSupportedError, "Format can't be used as depth stencil attachment");
1074     }
1075 }
1076 
ShaderTileImageTestInstance(Context & context,const TestParam * testParam)1077 ShaderTileImageTestInstance::ShaderTileImageTestInstance(Context &context, const TestParam *testParam)
1078     : TestInstance(context)
1079     , m_testParam(testParam)
1080     , m_vk(m_context.getDeviceInterface())
1081 {
1082     initialize();
1083 }
1084 
initialize()1085 void ShaderTileImageTestInstance::initialize()
1086 {
1087     generateCmdBuffer();
1088     generateAttachments();
1089     generateVertexBuffer();
1090     m_graphicsPipeline               = generateGraphicsPipeline(false, false, false);
1091     m_graphicsPipelineForHelperClass = generateGraphicsPipeline(true, true, true);
1092     generateComputePipeline();
1093 }
1094 
generateComputePipeline()1095 void ShaderTileImageTestInstance::generateComputePipeline()
1096 {
1097     const uint32_t attachmentSize = getColorAttachmentCount(m_testParam->testType);
1098     const VkDevice device         = m_context.getDevice();
1099 
1100     const Unique<VkShaderModule> cs(createShaderModule(m_vk, device, m_context.getBinaryCollection().get("comp"), 0));
1101 
1102     VkDescriptorSetLayoutCreateFlags layoutCreateFlags = 0;
1103 
1104     const VkDescriptorSetLayoutBinding bindings[] = {
1105         {
1106             0,                                // binding
1107             VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, // descriptorType
1108             1,                                // descriptorCount
1109             VK_SHADER_STAGE_COMPUTE_BIT,      // stageFlags
1110             DE_NULL,                          // pImmutableSamplers
1111         },
1112         {
1113             1,                                 // binding
1114             VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, // descriptorType
1115             1,                                 // descriptorCount
1116             VK_SHADER_STAGE_COMPUTE_BIT,       // stageFlags
1117             DE_NULL,                           // pImmutableSamplers
1118         },
1119     };
1120 
1121     // Create a layout and allocate a descriptor set for it.
1122     const VkDescriptorSetLayoutCreateInfo setLayoutCreateInfo = {
1123         vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // sType
1124         DE_NULL,                                                 // pNext
1125         layoutCreateFlags,                                       // flags
1126         sizeof(bindings) / sizeof(bindings[0]),                  // bindingCount
1127         &bindings[0]                                             // pBindings
1128     };
1129 
1130     m_computeDescriptorSetLayout = vk::createDescriptorSetLayout(m_vk, device, &setLayoutCreateInfo);
1131 
1132     const VkPipelineShaderStageCreateInfo csShaderCreateInfo = {
1133         VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
1134         DE_NULL,
1135         (VkPipelineShaderStageCreateFlags)0,
1136         VK_SHADER_STAGE_COMPUTE_BIT, // stage
1137         *cs,                         // shader
1138         "main",
1139         DE_NULL, // pSpecializationInfo
1140     };
1141 
1142     const VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = {
1143         VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // sType
1144         DE_NULL,                                       // pNext
1145         (VkPipelineLayoutCreateFlags)0,
1146         1,                                   // setLayoutCount
1147         &m_computeDescriptorSetLayout.get(), // pSetLayouts
1148         0,                                   // pushConstantRangeCount
1149         DE_NULL,                             // pPushConstantRanges
1150     };
1151 
1152     m_computePipelineLayout = createPipelineLayout(m_vk, device, &pipelineLayoutCreateInfo, NULL);
1153 
1154     const VkComputePipelineCreateInfo pipelineCreateInfo = {
1155         VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
1156         DE_NULL,
1157         0u,                       // flags
1158         csShaderCreateInfo,       // cs
1159         *m_computePipelineLayout, // layout
1160         (vk::VkPipeline)0,        // basePipelineHandle
1161         0u,                       // basePipelineIndex
1162     };
1163 
1164     m_computePipeline = createComputePipeline(m_vk, device, DE_NULL, &pipelineCreateInfo, NULL);
1165 
1166     VkDescriptorPoolCreateFlags poolCreateFlags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
1167 
1168     vk::DescriptorPoolBuilder poolBuilder;
1169     for (uint32_t i = 0; i < (int32_t)(sizeof(bindings) / sizeof(bindings[0])); ++i)
1170     {
1171         poolBuilder.addType(bindings[i].descriptorType, bindings[i].descriptorCount * attachmentSize);
1172     }
1173     m_descriptorPool = poolBuilder.build(m_vk, device, poolCreateFlags, attachmentSize);
1174 
1175     for (uint32_t i = 0; i < attachmentSize; ++i)
1176     {
1177         m_descriptorSets[i] = makeDescriptorSet(m_vk, device, *m_descriptorPool, *m_computeDescriptorSetLayout);
1178         VkDescriptorImageInfo imageInfo;
1179         VkDescriptorBufferInfo bufferInfo;
1180 
1181         VkWriteDescriptorSet w = {
1182             VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // sType
1183             DE_NULL,                                // pNext
1184             *m_descriptorSets[i],                   // dstSet
1185             (uint32_t)0,                            // dstBinding
1186             0,                                      // dstArrayElement
1187             1u,                                     // descriptorCount
1188             bindings[0].descriptorType,             // descriptorType
1189             &imageInfo,                             // pImageInfo
1190             &bufferInfo,                            // pBufferInfo
1191             DE_NULL,                                // pTexelBufferView
1192         };
1193 
1194         imageInfo    = makeDescriptorImageInfo(DE_NULL, *m_imageColorView[i], VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
1195         w.dstBinding = 0;
1196         w.descriptorType = bindings[0].descriptorType;
1197         m_vk.updateDescriptorSets(device, 1, &w, 0, NULL);
1198 
1199         bufferInfo       = makeDescriptorBufferInfo(m_imageBuffer[i]->object(), 0, VK_WHOLE_SIZE);
1200         w.dstBinding     = 1;
1201         w.descriptorType = bindings[1].descriptorType;
1202         m_vk.updateDescriptorSets(device, 1, &w, 0, NULL);
1203     }
1204 }
1205 
generateGraphicsPipeline(bool disableColor0Write,bool disableDepthWrite,bool disableStencilWrite)1206 Move<VkPipeline> ShaderTileImageTestInstance::generateGraphicsPipeline(bool disableColor0Write, bool disableDepthWrite,
1207                                                                        bool disableStencilWrite)
1208 {
1209     const VkDevice device = m_context.getDevice();
1210 
1211     VkPushConstantRange pushConstant;
1212     pushConstant.offset     = 0;
1213     pushConstant.size       = sizeof(uint32_t);
1214     pushConstant.stageFlags = (VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT);
1215 
1216     m_graphicsPipelineLayout = makePipelineLayout(m_vk, device, 0, nullptr, 1, &pushConstant);
1217     m_vertexModule           = createShaderModule(m_vk, device, m_context.getBinaryCollection().get("vert"), 0u);
1218     m_fragmentModule         = createShaderModule(m_vk, device, m_context.getBinaryCollection().get("frag"), 0u);
1219 
1220     const VkVertexInputBindingDescription vertexInputBindingDescription = {
1221         0,                           // uint32_t binding;
1222         sizeof(tcu::Vec2),           // uint32_t strideInBytes;
1223         VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputStepRate stepRate;
1224     };
1225 
1226     const VkVertexInputAttributeDescription vertexInputAttributeDescription = {
1227         0u,                      // uint32_t location;
1228         0u,                      // uint32_t binding;
1229         VK_FORMAT_R32G32_SFLOAT, // VkFormat format;
1230         0u,                      // uint32_t offsetInBytes;
1231     };
1232 
1233     const VkPipelineVertexInputStateCreateInfo vertexInputStateParams = {
1234         VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
1235         DE_NULL,                                                   // const void* pNext;
1236         0,                                                         // VkPipelineVertexInputStateCreateFlags flags;
1237         1u,                                                        // uint32_t bindingCount;
1238         &vertexInputBindingDescription,   // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
1239         1u,                               // uint32_t attributeCount;
1240         &vertexInputAttributeDescription, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
1241     };
1242 
1243     const VkPipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateInfo = {
1244         VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
1245         DE_NULL,                                                     // const void* pNext;
1246         (VkPipelineInputAssemblyStateCreateFlags)0,                  // VkPipelineInputAssemblyStateCreateFlags flags;
1247         VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,                         // VkPrimitiveTopology topology;
1248         VK_FALSE,                                                    // VkBool32 primitiveRestartEnable;
1249     };
1250 
1251     const VkViewport viewport{
1252         0, 0, static_cast<float>(m_testParam->frameBufferSize), static_cast<float>(m_testParam->frameBufferSize), 0, 1};
1253     const VkRect2D scissor{{0, 0}, {m_testParam->frameBufferSize, m_testParam->frameBufferSize}};
1254 
1255     const VkPipelineViewportStateCreateInfo pipelineViewportStateInfo = {
1256         VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
1257         DE_NULL,                                               // const void* pNext;
1258         (VkPipelineViewportStateCreateFlags)0,                 // VkPipelineViewportStateCreateFlags flags;
1259         1u,                                                    // uint32_t viewportCount;
1260         &viewport,                                             // const VkViewport* pViewports;
1261         1u,                                                    // uint32_t scissorCount;
1262         &scissor,                                              // const VkRect2D* pScissors;
1263     };
1264 
1265     const VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateInfo = {
1266         VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
1267         DE_NULL,                                                    // const void* pNext;
1268         0u,                                                         // VkPipelineRasterizationStateCreateFlags flags;
1269         VK_FALSE,                                                   // VkBool32 depthClampEnable;
1270         VK_FALSE,                                                   // VkBool32 rasterizerDiscardEnable;
1271         VK_POLYGON_MODE_FILL,                                       // VkPolygonMode polygonMode;
1272         VK_CULL_MODE_NONE,                                          // VkCullModeFlags cullMode;
1273         VK_FRONT_FACE_COUNTER_CLOCKWISE,                            // VkFrontFace frontFace;
1274         VK_FALSE,                                                   // VkBool32 depthBiasEnable;
1275         0.0f,                                                       // float depthBiasConstantFactor;
1276         0.0f,                                                       // float depthBiasClamp;
1277         0.0f,                                                       // float depthBiasSlopeFactor;
1278         1.0f,                                                       // float lineWidth;
1279     };
1280 
1281     const VkSampleMask sampleMask   = getSampleMask(m_testParam->testType);
1282     const VkSampleMask *pSampleMask = (m_testParam->testType == TestType::MsaaSampleMask) ? &sampleMask : DE_NULL;
1283     const bool sampleShadingEnable  = (m_testParam->testType != TestType::MsaaSampleMask);
1284 
1285     const VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo = {
1286         VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
1287         DE_NULL,                                                  // const void* pNext;
1288         0u,                                                       // VkPipelineMultisampleStateCreateFlags flags;
1289         m_testParam->m_sampleCount,                               // VkSampleCountFlagBits rasterizationSamples;
1290         sampleShadingEnable,                                      // VkBool32 sampleShadingEnable;
1291         1.0f,                                                     // float minSampleShading;
1292         pSampleMask,                                              // const VkSampleMask* pSampleMask;
1293         VK_FALSE,                                                 // VkBool32 alphaToCoverageEnable;
1294         VK_FALSE                                                  // VkBool32 alphaToOneEnable;
1295     };
1296 
1297     std::vector<VkPipelineColorBlendAttachmentState> colorBlendAttachmentState(
1298         getColorAttachmentCount(m_testParam->testType),
1299         {
1300             false,                                                // VkBool32 blendEnable;
1301             VK_BLEND_FACTOR_ONE,                                  // VkBlend srcBlendColor;
1302             VK_BLEND_FACTOR_ONE,                                  // VkBlend destBlendColor;
1303             VK_BLEND_OP_ADD,                                      // VkBlendOp blendOpColor;
1304             VK_BLEND_FACTOR_ONE,                                  // VkBlend srcBlendAlpha;
1305             VK_BLEND_FACTOR_ONE,                                  // VkBlend destBlendAlpha;
1306             VK_BLEND_OP_ADD,                                      // VkBlendOp blendOpAlpha;
1307             (VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT) // VkChannelFlags channelWriteMask;
1308         });
1309 
1310     if (disableColor0Write)
1311     {
1312         colorBlendAttachmentState[0].colorWriteMask = 0;
1313     }
1314 
1315     const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo = {
1316         VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
1317         DE_NULL,                                                  // const void* pNext;
1318         /* always needed */
1319         0,                                          // VkPipelineColorBlendStateCreateFlags flags;
1320         false,                                      // VkBool32 logicOpEnable;
1321         VK_LOGIC_OP_COPY,                           // VkLogicOp logicOp;
1322         (uint32_t)colorBlendAttachmentState.size(), // uint32_t attachmentCount;
1323         colorBlendAttachmentState.data(),           // const VkPipelineColorBlendAttachmentState* pAttachments;
1324         {0.0f, 0.0f, 0.0f, 0.0f},                   // float blendConst[4];
1325     };
1326 
1327     VkStencilOpState stencilOpState = {
1328         VK_STENCIL_OP_ZERO,               // VkStencilOp failOp;
1329         VK_STENCIL_OP_INCREMENT_AND_WRAP, // VkStencilOp passOp;
1330         VK_STENCIL_OP_INCREMENT_AND_WRAP, // VkStencilOp depthFailOp;
1331         VK_COMPARE_OP_ALWAYS,             // VkCompareOp compareOp;
1332         0xff,                             // uint32_t compareMask;
1333         0xff,                             // uint32_t writeMask;
1334         0,                                // uint32_t reference;
1335     };
1336 
1337     if (disableStencilWrite)
1338     {
1339         stencilOpState.failOp      = VK_STENCIL_OP_KEEP;
1340         stencilOpState.passOp      = VK_STENCIL_OP_KEEP;
1341         stencilOpState.depthFailOp = VK_STENCIL_OP_KEEP;
1342     }
1343 
1344     VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo = {
1345         VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
1346         // VkStructureType sType;
1347         DE_NULL, // const void* pNext;
1348         0,
1349         // VkPipelineDepthStencilStateCreateFlags flags;
1350         VK_TRUE,              // VkBool32 depthTestEnable;
1351         VK_TRUE,              // VkBool32 depthWriteEnable;
1352         VK_COMPARE_OP_ALWAYS, // VkCompareOp depthCompareOp;
1353         VK_FALSE,             // VkBool32 depthBoundsTestEnable;
1354         VK_TRUE,              // VkBool32 stencilTestEnable;
1355         stencilOpState,       // VkStencilOpState front;
1356         stencilOpState,       // VkStencilOpState back;
1357         0.0f,                 // float minDepthBounds;
1358         1.0f,                 // float maxDepthBounds;
1359     };
1360 
1361     if (disableDepthWrite)
1362     {
1363         pipelineDepthStencilStateInfo.depthWriteEnable = VK_FALSE;
1364     }
1365 
1366     std::vector<VkFormat> colorsAttachmentFormats(getColorAttachmentCount(m_testParam->testType),
1367                                                   m_testParam->colorFormat);
1368     const tcu::TextureFormat depthStencilTexFormat = mapVkFormat(m_testParam->depthStencilFormat);
1369     VkFormat depthFormat =
1370         tcu::hasDepthComponent(depthStencilTexFormat.order) ? m_testParam->depthStencilFormat : VK_FORMAT_UNDEFINED;
1371     VkFormat stencilFormat =
1372         tcu::hasStencilComponent(depthStencilTexFormat.order) ? m_testParam->depthStencilFormat : VK_FORMAT_UNDEFINED;
1373     const VkPipelineRenderingCreateInfoKHR renderingCreateInfo{
1374         VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,  // VkStructureType sType;
1375         DE_NULL,                                               // const void* pNext;
1376         0u,                                                    // uint32_t viewMask;
1377         static_cast<uint32_t>(colorsAttachmentFormats.size()), // uint32_t colorAttachmentCount;
1378         colorsAttachmentFormats.data(),                        // const VkFormat* pColorAttachmentFormats;
1379         depthFormat,                                           // VkFormat depthAttachmentFormat;
1380         stencilFormat,                                         // VkFormat stencilAttachmentFormat;
1381     };
1382 
1383     const VkPipelineShaderStageCreateInfo pShaderStages[] = {
1384         {
1385             VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
1386             DE_NULL,                                             // const void*  pNext;
1387             (VkPipelineShaderStageCreateFlags)0,                 // VkPipelineShaderStageCreateFlags flags;
1388             VK_SHADER_STAGE_VERTEX_BIT,                          // VkShaderStageFlagBits stage;
1389             *m_vertexModule,                                     // VkShaderModule module;
1390             "main",                                              // const char* pName;
1391             DE_NULL,                                             // const VkSpecializationInfo* pSpecializationInfo;
1392         },
1393         {
1394             VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
1395             DE_NULL,                                             // const void* pNext;
1396             (VkPipelineShaderStageCreateFlags)0,                 // VkPipelineShaderStageCreateFlags flags;
1397             VK_SHADER_STAGE_FRAGMENT_BIT,                        // VkShaderStageFlagBits stage;
1398             *m_fragmentModule,                                   // VkShaderModule module;
1399             "main",                                              // const char* pName;
1400             DE_NULL,                                             // const VkSpecializationInfo* pSpecializationInfo;
1401         },
1402     };
1403 
1404     const VkGraphicsPipelineCreateInfo graphicsPipelineInfo = {
1405         VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
1406         &renderingCreateInfo,                            // const void* pNext;
1407         (VkPipelineCreateFlags)0,                        // VkPipelineCreateFlags flags;
1408         2u,                                              // uint32_t stageCount;
1409         pShaderStages,                                   // const VkPipelineShaderStageCreateInfo* pStages;
1410         &vertexInputStateParams,         // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
1411         &pipelineInputAssemblyStateInfo, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
1412         DE_NULL,                         // const VkPipelineTessellationStateCreateInfo* pTessellationState;
1413         &pipelineViewportStateInfo,      // const VkPipelineViewportStateCreateInfo* pViewportState;
1414         &pipelineRasterizationStateInfo, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState;
1415         &pipelineMultisampleStateInfo,   // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
1416         &pipelineDepthStencilStateInfo,  // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
1417         &pipelineColorBlendStateInfo,    // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
1418         DE_NULL,                         // const VkPipelineDynamicStateCreateInfo* pDynamicState;
1419         *m_graphicsPipelineLayout,       // VkPipelineLayout layout;
1420         DE_NULL,                         // VkRenderPass renderPass;
1421         0u,                              // uint32_t subpass;
1422         DE_NULL,                         // VkPipeline basePipelineHandle;
1423         0,                               // int32_t basePipelineIndex;
1424     };
1425 
1426     return createGraphicsPipeline(m_vk, device, DE_NULL, &graphicsPipelineInfo);
1427 }
1428 
generateAttachments()1429 void ShaderTileImageTestInstance::generateAttachments()
1430 {
1431     const VkDevice device = m_context.getDevice();
1432     Allocator &allocator  = m_context.getDefaultAllocator();
1433 
1434     auto makeImageCreateInfo = [](const VkFormat format, uint32_t imageSize, VkSampleCountFlagBits sampleCount,
1435                                   VkImageUsageFlags usage) -> VkImageCreateInfo
1436     {
1437         const VkImageCreateInfo imageParams = {
1438             VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,   // VkStructureType sType;
1439             DE_NULL,                               // const void* pNext;
1440             (VkImageCreateFlags)0,                 // VkImageCreateFlags flags;
1441             VK_IMAGE_TYPE_2D,                      // VkImageType imageType;
1442             format,                                // VkFormat format;
1443             makeExtent3D(imageSize, imageSize, 1), // VkExtent3D extent;
1444             1u,                                    // uint32_t mipLevels;
1445             1u,                                    // uint32_t arrayLayers;
1446             sampleCount,                           // VkSampleCountFlagBits samples;
1447             VK_IMAGE_TILING_OPTIMAL,               // VkImageTiling tiling;
1448             usage,                                 // VkImageUsageFlags usage;
1449             VK_SHARING_MODE_EXCLUSIVE,             // VkSharingMode sharingMode;
1450             0u,                                    // uint32_t queueFamilyIndexCount;
1451             DE_NULL,                               // const uint32_t* pQueueFamilyIndices;
1452             VK_IMAGE_LAYOUT_UNDEFINED,             // VkImageLayout initialLayout;
1453         };
1454         return imageParams;
1455     };
1456 
1457     // Color Attachment
1458     {
1459         constexpr uint32_t imageBufferPixelSize = sizeof(uint32_t) * 2; // always uvec2 type
1460         const VkImageUsageFlags imageUsage =
1461             VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1462         const VkDeviceSize imageBufferSize = m_testParam->frameBufferSize * m_testParam->frameBufferSize *
1463                                              imageBufferPixelSize * getSampleCount(m_testParam->m_sampleCount);
1464         const VkImageSubresourceRange imageSubresource =
1465             makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
1466         const VkImageCreateInfo imageInfo = makeImageCreateInfo(m_testParam->colorFormat, m_testParam->frameBufferSize,
1467                                                                 m_testParam->m_sampleCount, imageUsage);
1468         const VkBufferCreateInfo bufferInfo = makeBufferCreateInfo(
1469             imageBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1470 
1471         const uint32_t attachmentCount = getColorAttachmentCount(m_testParam->testType);
1472         for (uint32_t i = 0; i < attachmentCount; ++i)
1473         {
1474             m_imageColor[i]      = makeImage(m_vk, device, imageInfo);
1475             m_imageColorAlloc[i] = bindImage(m_vk, device, allocator, *m_imageColor[i], MemoryRequirement::Any);
1476             m_imageBuffer[i] =
1477                 Draw::Buffer::createAndAlloc(m_vk, device, bufferInfo, allocator, MemoryRequirement::HostVisible);
1478             m_imageColorView[i] = makeImageView(m_vk, device, *m_imageColor[i], VK_IMAGE_VIEW_TYPE_2D,
1479                                                 m_testParam->colorFormat, imageSubresource);
1480         }
1481 
1482         m_imageColorBufferHostPtr = static_cast<uint32_t *>(m_imageBuffer[0]->getHostPtr());
1483     }
1484 
1485     // depth/stencil attachment.
1486     {
1487         const tcu::TextureFormat depthStencilFormat = mapVkFormat(m_testParam->depthStencilFormat);
1488         const VkImageUsageFlags imageUsage =
1489             VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1490 
1491         VkImageAspectFlags aspect = 0;
1492         if (tcu::hasDepthComponent(depthStencilFormat.order))
1493         {
1494             aspect |= VK_IMAGE_ASPECT_DEPTH_BIT;
1495         }
1496         if (tcu::hasStencilComponent(depthStencilFormat.order))
1497         {
1498             aspect |= VK_IMAGE_ASPECT_STENCIL_BIT;
1499         }
1500 
1501         const VkImageCreateInfo imageInfo = makeImageCreateInfo(
1502             m_testParam->depthStencilFormat, m_testParam->frameBufferSize, m_testParam->m_sampleCount, imageUsage);
1503 
1504         const VkImageSubresourceRange imageSubresource = makeImageSubresourceRange(aspect, 0u, 1u, 0u, 1u);
1505 
1506         m_imageDepthStencil      = makeImage(m_vk, device, imageInfo);
1507         m_imageDepthStencilAlloc = bindImage(m_vk, device, allocator, *m_imageDepthStencil, MemoryRequirement::Any);
1508         m_imageDepthStencilView  = makeImageView(m_vk, device, *m_imageDepthStencil, VK_IMAGE_VIEW_TYPE_2D,
1509                                                  m_testParam->depthStencilFormat, imageSubresource);
1510     }
1511 }
1512 
generateVertexBuffer()1513 void ShaderTileImageTestInstance::generateVertexBuffer()
1514 {
1515     const uint32_t drawCount         = getDrawCallCount(m_testParam);
1516     const uint32_t patchCountPerDraw = getPatchesPerDrawCount(m_testParam->multiplePatchesPerDraw);
1517     const uint32_t queueFamilyIndex  = m_context.getUniversalQueueFamilyIndex();
1518     const VkDevice device            = m_context.getDevice();
1519     Allocator &allocator             = m_context.getDefaultAllocator();
1520     std::vector<tcu::Vec2> vbo;
1521     for (uint32_t patchIndex = 0; patchIndex < (patchCountPerDraw * drawCount); patchIndex++)
1522     {
1523         // _____
1524         // |  /
1525         // | /
1526         // |/
1527         vbo.emplace_back(tcu::Vec2(-1, -1));
1528         vbo.emplace_back(tcu::Vec2(1, 1));
1529         vbo.emplace_back(tcu::Vec2(-1, 1));
1530 
1531         if (getVertexCountPerPatch(m_testParam) == 6)
1532         {
1533             if (isHelperClassTest(m_testParam->testType) && patchIndex == 0)
1534             {
1535                 // helper class cases render the first patch like follow.
1536                 // _____
1537                 // |  /
1538                 // | /
1539                 // |/
1540                 // So, 3 of second triangle is dummy.
1541                 vbo.emplace_back(tcu::Vec2(-1, -1));
1542                 vbo.emplace_back(tcu::Vec2(-1, -1));
1543                 vbo.emplace_back(tcu::Vec2(-1, -1));
1544             }
1545             else
1546             {
1547                 // Other 6 vertices cases render like follow
1548                 // _____
1549                 // |  /|
1550                 // | / |
1551                 // |/__|
1552                 vbo.emplace_back(tcu::Vec2(-1, -1));
1553                 vbo.emplace_back(tcu::Vec2(1, -1));
1554                 vbo.emplace_back(tcu::Vec2(1, 1));
1555             }
1556         }
1557     }
1558 
1559     const size_t dataSize = vbo.size() * sizeof(tcu::Vec2);
1560     {
1561         const VkBufferCreateInfo bufferInfo = {
1562             VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
1563             DE_NULL,                              // const void* pNext;
1564             0u,                                   // VkBufferCreateFlags flags;
1565             dataSize,                             // VkDeviceSize size;
1566             VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,    // VkBufferUsageFlags usage;
1567             VK_SHARING_MODE_EXCLUSIVE,            // VkSharingMode sharingMode;
1568             1u,                                   // uint32_t queueFamilyCount;
1569             &queueFamilyIndex                     // const uint32_t* pQueueFamilyIndices;
1570         };
1571         m_vertexBuffer =
1572             Draw::Buffer::createAndAlloc(m_vk, device, bufferInfo, allocator, MemoryRequirement::HostVisible);
1573     }
1574 
1575     /* Load vertices into vertex buffer */
1576     deMemcpy(m_vertexBuffer->getBoundMemory().getHostPtr(), vbo.data(), dataSize);
1577     flushAlloc(m_vk, device, m_vertexBuffer->getBoundMemory());
1578 }
generateCmdBuffer()1579 void ShaderTileImageTestInstance::generateCmdBuffer()
1580 {
1581     const VkDevice device = m_context.getDevice();
1582 
1583     m_cmdPool   = createCommandPool(m_vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
1584                                     m_context.getUniversalQueueFamilyIndex());
1585     m_cmdBuffer = allocateCommandBuffer(m_vk, device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1586 }
1587 
iterate()1588 tcu::TestStatus ShaderTileImageTestInstance::iterate()
1589 {
1590     rendering();
1591     return checkResult();
1592 }
1593 
getResultValue(uint32_t fx,uint32_t fy,uint32_t fs,uint32_t renderTargetID) const1594 uint32_t ShaderTileImageTestInstance::getResultValue(uint32_t fx, uint32_t fy, uint32_t fs,
1595                                                      uint32_t renderTargetID) const
1596 {
1597     const uint32_t *resultData =
1598         static_cast<const uint32_t *>(m_imageBuffer[renderTargetID]->getBoundMemory().getHostPtr());
1599     const uint32_t sampleCount = getSampleCount(m_testParam->m_sampleCount);
1600     const uint32_t index       = (((fy * m_testParam->frameBufferSize) + fx) * sampleCount + fs) * 2; // 2 is for xy
1601     if (resultData[index] != 0)                                                                       // error
1602     {
1603         return 0xFFFFFFFF;
1604     }
1605 
1606     return resultData[index + 1]; // y value
1607 }
1608 
simulate(uint32_t fx,uint32_t fy,uint32_t fs,uint32_t renderTargetID) const1609 uint32_t ShaderTileImageTestInstance::simulate(uint32_t fx, uint32_t fy, uint32_t fs, uint32_t renderTargetID) const
1610 {
1611     const uint32_t totalLayerCount =
1612         getDrawCallCount(m_testParam) * getPatchesPerDrawCount(m_testParam->multiplePatchesPerDraw);
1613 
1614     if (m_testParam->testType == TestType::MsaaSampleMask)
1615     {
1616         uint32_t expectedValue = 0;
1617 
1618         if (((getSampleMask(m_testParam->testType) >> fs) & 0x1) == 0x1)
1619         {
1620             expectedValue = totalLayerCount + renderTargetID;
1621         }
1622         return expectedValue;
1623     }
1624     if (m_testParam->testType == TestType::Stencil)
1625     {
1626         // stencil test doesn't add fragment sample ID to the output;
1627         const uint32_t expectedValue = totalLayerCount + renderTargetID;
1628         return expectedValue;
1629     }
1630     if (isHelperClassTest(m_testParam->testType))
1631     {
1632         // ________      ________      ________
1633         // 1|1|1|0|      0|0|*|1|      1|1|#|2|
1634         // 1|1|0|0|      0|0|1|*|      1|1|2|#|
1635         // 1|0|0|0|  =>  *|1|0|0|  =>  #|2|1|1|
1636         // 0|0|0|0|      1|*|0|0|      2|#|1|1|
1637         // ________      ________      ________
1638         // raster       max(dx,dy)    result(+1)
1639         // *(#): max(dx, dy) could be 0(1) or 1(2).
1640         if ((fx) == (fy))
1641         {
1642             return kDerivative1; // derivative is 1 because of coverage. (+1) for differentiate clear value
1643         }
1644         else
1645         {
1646             return kDerivative0; // 0, fill all or fill none for quad. (+1) for differentiate clear value
1647         }
1648     }
1649     else
1650     {
1651         const uint32_t expectedValue = totalLayerCount + renderTargetID + fs;
1652         return expectedValue;
1653     }
1654 }
1655 
checkResult() const1656 tcu::TestStatus ShaderTileImageTestInstance::checkResult() const
1657 {
1658     const VkDevice device = m_context.getDevice();
1659 
1660     qpTestResult res                   = QP_TEST_RESULT_PASS;
1661     const uint32_t sampleCount         = getSampleCount(m_testParam->m_sampleCount);
1662     const uint32_t attachmentCount     = getColorAttachmentCount(m_testParam->testType);
1663     const uint32_t vertexCountPerPatch = getVertexCountPerPatch(m_testParam);
1664     // Loop over all samples in the same fragment
1665 
1666     for (uint32_t rt = 0; (res == QP_TEST_RESULT_PASS) && rt < attachmentCount; rt++)
1667     {
1668         // Result of Helper Class test valid only for the rt 1
1669         invalidateAlloc(m_vk, device, m_imageBuffer[rt]->getBoundMemory());
1670 
1671         if (rt != 1 && isHelperClassTest(m_testParam->testType))
1672         {
1673             continue;
1674         }
1675 
1676         for (uint32_t fy = 0; (res == QP_TEST_RESULT_PASS) && fy < m_testParam->frameBufferSize; ++fy)
1677         {
1678             for (uint32_t fx = 0; (res == QP_TEST_RESULT_PASS) && fx < m_testParam->frameBufferSize; ++fx)
1679             {
1680                 for (uint32_t fs = 0; (res == QP_TEST_RESULT_PASS) && fs < sampleCount; ++fs)
1681                 {
1682                     const uint32_t expectedValue = simulate(fx, fy, fs, rt);
1683                     const uint32_t resultValue   = getResultValue(fx, fy, fs, rt);
1684 
1685                     if (isHelperClassTest(m_testParam->testType))
1686                     {
1687                         // ________      ________      ________
1688                         // 1|1|1|0|      0|0|*|1|      1|1|#|2|
1689                         // 1|1|0|0|      0|0|1|*|      1|1|2|#|
1690                         // 1|0|0|0|  =>  *|1|0|0|  =>  #|2|1|1|
1691                         // 0|0|0|0|      1|*|0|0|      2|#|1|1|
1692                         // ________      ________      ________
1693                         // raster       max(dx,dy)    result(+1)
1694                         // *(#): max(dx, dy) could be 0(1) or 1(2).
1695                         if (expectedValue != resultValue)
1696                         {
1697                             if (std::abs(static_cast<int32_t>(fx - fy)) != 1 || resultValue != kDerivative1)
1698                             {
1699                                 res = QP_TEST_RESULT_FAIL;
1700                                 break;
1701                             }
1702                         }
1703                     }
1704                     else if (vertexCountPerPatch == 6) // Fill full quad to the framebuffer
1705                     {
1706                         if (expectedValue != resultValue)
1707                         {
1708                             res = QP_TEST_RESULT_FAIL;
1709                             break;
1710                         }
1711                     }
1712                     else // Fill a triangle to the framebuffer, check half of framebuffer
1713                     {
1714                         if (fy > fx) // inside of triangle
1715                         {
1716                             if (expectedValue != resultValue) // not expected value
1717                             {
1718                                 res = QP_TEST_RESULT_FAIL;
1719                                 break;
1720                             }
1721                         }
1722                         else // outside of filling triangle or triangle edge
1723                         {
1724                             if (resultValue != 0 && resultValue != expectedValue) // can be not filling
1725                             {
1726                                 res = QP_TEST_RESULT_FAIL;
1727                                 break;
1728                             }
1729                         }
1730                     }
1731                 }
1732             }
1733         }
1734     }
1735 
1736     return tcu::TestStatus(res, qpGetTestResultName(res));
1737 }
1738 
rendering()1739 void ShaderTileImageTestInstance::rendering()
1740 {
1741     const VkDevice device = m_context.getDevice();
1742     const VkQueue queue   = m_context.getUniversalQueue();
1743 
1744     beginCommandBuffer(m_vk, *m_cmdBuffer);
1745 
1746     // begin render pass
1747     const VkClearValue clearValue   = {}; // { 0, 0, 0, 0 }
1748     const VkClearValue dsClearValue = {}; // .depth = 0.0f, .stencil = 0
1749     const VkRect2D renderArea       = {{0, 0}, {m_testParam->frameBufferSize, m_testParam->frameBufferSize}};
1750 
1751     const uint32_t colorAttachmentCount = getColorAttachmentCount(m_testParam->testType);
1752 
1753     std::vector<VkRenderingAttachmentInfoKHR> colorAttachments;
1754     for (uint32_t colorIndex = 0; colorIndex < colorAttachmentCount; colorIndex++)
1755     {
1756         const VkRenderingAttachmentInfoKHR renderingAtachInfo = {
1757             VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR, // VkStructureType sType;
1758             DE_NULL,                                         // const void* pNext;
1759             *m_imageColorView[colorIndex],                   // VkImageView imageView;
1760             VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,        // VkImageLayout imageLayout;
1761             VK_RESOLVE_MODE_NONE,                            // VkResolveModeFlagBits resolveMode;
1762             DE_NULL,                                         // VkImageView resolveImageView;
1763             VK_IMAGE_LAYOUT_UNDEFINED,                       // VkImageLayout resolveImageLayout;
1764             VK_ATTACHMENT_LOAD_OP_CLEAR,                     // VkAttachmentLoadOp loadOp;
1765             VK_ATTACHMENT_STORE_OP_STORE,                    // VkAttachmentStoreOp storeOp;
1766             clearValue,                                      // VkClearValue clearValue;
1767         };
1768 
1769         colorAttachments.push_back(renderingAtachInfo);
1770     }
1771 
1772     const tcu::TextureFormat depthStencilFormat = mapVkFormat(m_testParam->depthStencilFormat);
1773     const bool hasDepth                         = tcu::hasDepthComponent(depthStencilFormat.order);
1774     const bool hasStencil                       = tcu::hasStencilComponent(depthStencilFormat.order);
1775     VkImageLayout depthStencilLayout            = VK_IMAGE_LAYOUT_UNDEFINED;
1776     VkImageAspectFlags depthStencilAspect       = 0;
1777     if (hasDepth && hasStencil)
1778     {
1779         depthStencilLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
1780         depthStencilAspect = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
1781     }
1782     else if (hasDepth)
1783     {
1784         depthStencilLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL;
1785         depthStencilAspect = VK_IMAGE_ASPECT_DEPTH_BIT;
1786     }
1787     else if (hasStencil)
1788     {
1789         depthStencilLayout = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL;
1790         depthStencilAspect = VK_IMAGE_ASPECT_STENCIL_BIT;
1791     }
1792 
1793     const VkRenderingAttachmentInfoKHR depthStencilAttachment = {
1794         VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR, // VkStructureType sType;
1795         DE_NULL,                                         // const void* pNext;
1796         *m_imageDepthStencilView,                        // VkImageView imageView;
1797         depthStencilLayout,                              // VkImageLayout imageLayout;
1798         VK_RESOLVE_MODE_NONE,                            // VkResolveModeFlagBits resolveMode;
1799         DE_NULL,                                         // VkImageView resolveImageView;
1800         VK_IMAGE_LAYOUT_UNDEFINED,                       // VkImageLayout resolveImageLayout;
1801         VK_ATTACHMENT_LOAD_OP_CLEAR,                     // VkAttachmentLoadOp loadOp;
1802         VK_ATTACHMENT_STORE_OP_STORE,                    // VkAttachmentStoreOp storeOp;
1803         dsClearValue,                                    // VkClearValue clearValue;
1804     };
1805 
1806     const VkRenderingInfoKHR renderingInfo = {
1807         VK_STRUCTURE_TYPE_RENDERING_INFO_KHR,           // VkStructureType sType;
1808         DE_NULL,                                        // const void* pNext;
1809         0,                                              // VkRenderingFlagsKHR flags;
1810         renderArea,                                     // VkRect2D renderArea;
1811         1u,                                             // uint32_t layerCount;
1812         0u,                                             // uint32_t viewMask;
1813         static_cast<uint32_t>(colorAttachments.size()), // uint32_t colorAttachmentCount;
1814         colorAttachments.data(),                        // const VkRenderingAttachmentInfoKHR* pColorAttachments;
1815         hasDepth ? &depthStencilAttachment : DE_NULL,   // const VkRenderingAttachmentInfoKHR* pDepthAttachment;
1816         hasStencil ? &depthStencilAttachment : DE_NULL  // const VkRenderingAttachmentInfoKHR* pStencilAttachment;
1817     };
1818 
1819     for (uint32_t colorIndex = 0; colorIndex < colorAttachmentCount; colorIndex++)
1820     {
1821         transition2DImage(m_vk, *m_cmdBuffer, *m_imageColor[colorIndex], VK_IMAGE_ASPECT_COLOR_BIT,
1822                           VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 0,
1823                           VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
1824                           VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
1825     }
1826 
1827     transition2DImage(m_vk, *m_cmdBuffer, *m_imageDepthStencil, depthStencilAspect, VK_IMAGE_LAYOUT_UNDEFINED,
1828                       depthStencilLayout, 0, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
1829                       VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
1830                       VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT);
1831 
1832     m_vk.cmdBeginRendering(*m_cmdBuffer, &renderingInfo);
1833 
1834     // vertex input setup
1835     const VkBuffer vertexBuffer = m_vertexBuffer->object();
1836 
1837     for (uint32_t drawIndex = 0; drawIndex < getDrawCallCount(m_testParam); drawIndex++)
1838     {
1839         // pipeline setup
1840         if (drawIndex == 1 && isHelperClassTest(m_testParam->testType))
1841         {
1842             m_vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipelineForHelperClass);
1843         }
1844         else
1845         {
1846             m_vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipeline);
1847         }
1848 
1849         const uint32_t vertexCountPerPatch = getVertexCountPerPatch(m_testParam);
1850         const uint32_t vertexCount = vertexCountPerPatch * getPatchesPerDrawCount(m_testParam->multiplePatchesPerDraw);
1851         m_vk.cmdPushConstants(*m_cmdBuffer, *m_graphicsPipelineLayout,
1852                               (VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT), 0, sizeof(uint32_t),
1853                               &drawIndex);
1854 
1855         const VkDeviceSize vertexBufferOffset = (vertexCount * drawIndex) * sizeof(tcu::Vec2);
1856         m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
1857 
1858         if (!m_testParam->coherent)
1859         {
1860             VkMemoryBarrier2KHR memoryBarrierForColor = {
1861                 VK_STRUCTURE_TYPE_MEMORY_BARRIER_2_KHR,              // sType
1862                 DE_NULL,                                             // pNext
1863                 VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT_KHR, // srcStageMask
1864                 VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT_KHR,          // srcAccessMask
1865                 VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT_KHR, // dstStageMask
1866                 VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT_KHR            // dstAccessMask
1867             };
1868 
1869             VkMemoryBarrier2KHR memoryBarrierForDepthStencil = {
1870                 VK_STRUCTURE_TYPE_MEMORY_BARRIER_2_KHR, // sType
1871                 DE_NULL,                                // pNext
1872                 VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT |
1873                     VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT,    // srcStageMask
1874                 VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT_KHR, // srcAccessMask
1875                 VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT |
1876                     VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT,  // dstStageMask
1877                 VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT_KHR // dstAccessMask
1878             };
1879 
1880             VkMemoryBarrier2KHR *memoryBarrier =
1881                 (m_testParam->testType == TestType::Depth) || (m_testParam->testType == TestType::Stencil) ?
1882                     &memoryBarrierForDepthStencil :
1883                     &memoryBarrierForColor;
1884 
1885             VkDependencyInfoKHR dependencyInfo{
1886                 VK_STRUCTURE_TYPE_DEPENDENCY_INFO, // sType
1887                 DE_NULL,                           // pNext
1888                 VK_DEPENDENCY_BY_REGION_BIT,       //dependency flags
1889                 1,                                 //memory barrier count
1890                 memoryBarrier,                     //memory barrier
1891                 0,                                 // bufferMemoryBarrierCount
1892                 DE_NULL,                           // pBufferMemoryBarriers
1893                 0,                                 // imageMemoryBarrierCount
1894                 DE_NULL,                           // pImageMemoryBarriers
1895             };
1896             m_vk.cmdPipelineBarrier2(*m_cmdBuffer, &dependencyInfo);
1897         }
1898 
1899         m_vk.cmdDraw(*m_cmdBuffer, vertexCount, 1, 0, 0u);
1900     }
1901     m_vk.cmdEndRendering(*m_cmdBuffer);
1902 
1903     for (uint32_t colorIndex = 0; colorIndex < colorAttachmentCount; colorIndex++)
1904     {
1905 
1906         transition2DImage(m_vk, *m_cmdBuffer, *m_imageColor[colorIndex], VK_IMAGE_ASPECT_COLOR_BIT,
1907                           VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
1908                           VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT,
1909                           VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
1910                           VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
1911     }
1912 
1913     VkMemoryBarrier memBarrier = {
1914         VK_STRUCTURE_TYPE_MEMORY_BARRIER, // sType
1915         DE_NULL,                          // pNext
1916         0u,                               // srcAccessMask
1917         0u,                               // dstAccessMask
1918     };
1919     memBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
1920     memBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
1921     m_vk.cmdPipelineBarrier(*m_cmdBuffer,
1922                             VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
1923                             VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 1, &memBarrier, 0, DE_NULL, 0, DE_NULL);
1924 
1925     m_vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_computePipeline);
1926 
1927     // Copy color images to buffer memory
1928     for (uint32_t attachmentIndex = 0; attachmentIndex < colorAttachmentCount; attachmentIndex++)
1929     {
1930         m_vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_computePipelineLayout, 0u, 1,
1931                                    &*m_descriptorSets[attachmentIndex], 0u, DE_NULL);
1932 
1933         m_vk.cmdDispatch(*m_cmdBuffer, m_testParam->frameBufferSize, m_testParam->frameBufferSize, 1);
1934     }
1935     memBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
1936     memBarrier.dstAccessMask = VK_ACCESS_HOST_READ_BIT;
1937     m_vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0, 1,
1938                             &memBarrier, 0, DE_NULL, 0, DE_NULL);
1939 
1940     VK_CHECK(m_vk.endCommandBuffer(*m_cmdBuffer));
1941 
1942     submitCommandsAndWait(m_vk, device, queue, m_cmdBuffer.get());
1943 }
1944 
formatToName(VkFormat format)1945 std::string formatToName(VkFormat format)
1946 {
1947     const std::string formatStr = de::toString(format);
1948     const std::string prefix    = "VK_FORMAT_";
1949 
1950     DE_ASSERT(formatStr.substr(0, prefix.length()) == prefix);
1951 
1952     return de::toLower(formatStr.substr(prefix.length()));
1953 }
1954 
createShaderTileImageTestVariations(tcu::TestContext & testCtx,tcu::TestCaseGroup * gr)1955 void createShaderTileImageTestVariations(tcu::TestContext &testCtx, tcu::TestCaseGroup *gr)
1956 {
1957     struct TestTypeParam
1958     {
1959         TestType value;
1960         const char *name;
1961     };
1962 
1963     struct BoolParam
1964     {
1965         bool value;
1966         const char *name;
1967     };
1968 
1969     struct VkSampleCountFlagParam
1970     {
1971         VkSampleCountFlagBits value;
1972         const char *name;
1973     };
1974 
1975     const std::vector<BoolParam> coherentParams = {{true, "coherent"}, {false, "non_coherent"}};
1976 
1977     const std::vector<TestTypeParam> testTypeParams = {
1978         {TestType::Color, "color"},
1979         {TestType::MultiRenderTarget, "mrt"},
1980         {TestType::MultiRenderTargetDynamicIndex, "mrt_dynamic_index"},
1981         {TestType::MsaaSampleMask, "msaa_sample_mask"},
1982         {TestType::HelperClassColor, "helper_class_color"},
1983         {TestType::HelperClassDepth, "helper_class_depth"},
1984         {TestType::HelperClassStencil, "helper_class_stencil"},
1985         {TestType::Depth, "depth"},
1986         {TestType::Stencil, "stencil"},
1987     };
1988 
1989     const std::vector<VkSampleCountFlagParam> sampleCountParams = {
1990         {VK_SAMPLE_COUNT_1_BIT, "samples_1"},   {VK_SAMPLE_COUNT_2_BIT, "samples_2"},
1991         {VK_SAMPLE_COUNT_4_BIT, "samples_4"},   {VK_SAMPLE_COUNT_8_BIT, "samples_8"},
1992         {VK_SAMPLE_COUNT_16_BIT, "samples_16"}, {VK_SAMPLE_COUNT_32_BIT, "samples_32"},
1993     };
1994 
1995     const std::vector<BoolParam> multiDrawsParams = {{false, "single_draw"}, {true, "multi_draws"}};
1996 
1997     const std::vector<BoolParam> multiPatchParams = {{false, "single_patch"}, {true, "multi_patches"}};
1998 
1999     const std::vector<VkFormat> formats = {VK_FORMAT_R5G6B5_UNORM_PACK16,
2000                                            VK_FORMAT_R8G8_UNORM,
2001                                            VK_FORMAT_R8G8_SNORM,
2002                                            VK_FORMAT_R8G8_UINT,
2003                                            VK_FORMAT_R8G8_SINT,
2004                                            VK_FORMAT_R8G8B8A8_UNORM,
2005                                            VK_FORMAT_R8G8B8A8_SNORM,
2006                                            VK_FORMAT_R8G8B8A8_UINT,
2007                                            VK_FORMAT_R8G8B8A8_SINT,
2008                                            VK_FORMAT_R8G8B8A8_SRGB,
2009                                            VK_FORMAT_A8B8G8R8_UNORM_PACK32,
2010                                            VK_FORMAT_A8B8G8R8_SNORM_PACK32,
2011                                            VK_FORMAT_A8B8G8R8_UINT_PACK32,
2012                                            VK_FORMAT_A8B8G8R8_SINT_PACK32,
2013                                            VK_FORMAT_A8B8G8R8_SRGB_PACK32,
2014                                            VK_FORMAT_B8G8R8A8_UNORM,
2015                                            VK_FORMAT_B8G8R8A8_SRGB,
2016                                            VK_FORMAT_A2R10G10B10_UNORM_PACK32,
2017                                            VK_FORMAT_A2B10G10R10_UNORM_PACK32,
2018                                            VK_FORMAT_A2B10G10R10_UINT_PACK32,
2019                                            VK_FORMAT_R16G16_UNORM,
2020                                            VK_FORMAT_R16G16_SNORM,
2021                                            VK_FORMAT_R16G16_UINT,
2022                                            VK_FORMAT_R16G16_SINT,
2023                                            VK_FORMAT_R16G16_SFLOAT,
2024                                            VK_FORMAT_R16G16B16A16_UNORM,
2025                                            VK_FORMAT_R16G16B16A16_SNORM,
2026                                            VK_FORMAT_R16G16B16A16_UINT,
2027                                            VK_FORMAT_R16G16B16A16_SINT,
2028                                            VK_FORMAT_R16G16B16A16_SFLOAT,
2029                                            VK_FORMAT_R32G32_UINT,
2030                                            VK_FORMAT_R32G32_SINT,
2031                                            VK_FORMAT_R32G32_SFLOAT,
2032                                            VK_FORMAT_R32G32B32A32_UINT,
2033                                            VK_FORMAT_R32G32B32A32_SINT,
2034                                            VK_FORMAT_R32G32B32A32_SFLOAT,
2035                                            VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16,
2036 
2037                                            VK_FORMAT_D16_UNORM,
2038                                            VK_FORMAT_X8_D24_UNORM_PACK32,
2039                                            VK_FORMAT_D32_SFLOAT,
2040                                            VK_FORMAT_S8_UINT,
2041                                            VK_FORMAT_D16_UNORM_S8_UINT,
2042                                            VK_FORMAT_D24_UNORM_S8_UINT,
2043                                            VK_FORMAT_D32_SFLOAT_S8_UINT};
2044 
2045     tcu::TestCaseGroup *subGroup = nullptr;
2046     std::vector<tcu::TestCaseGroup *> testGroupStack;
2047     testGroupStack.push_back(gr);
2048 
2049     for (const BoolParam &coherentParam : coherentParams)
2050     {
2051         subGroup = (new tcu::TestCaseGroup(testCtx, coherentParam.name));
2052         testGroupStack.back()->addChild(subGroup);
2053         testGroupStack.push_back(subGroup);
2054         for (const TestTypeParam &testTypeParam : testTypeParams)
2055         {
2056             subGroup = new tcu::TestCaseGroup(testCtx, testTypeParam.name);
2057             testGroupStack.back()->addChild(subGroup);
2058             testGroupStack.push_back(subGroup);
2059 
2060             for (const VkSampleCountFlagParam &sampleCountParam : sampleCountParams)
2061             {
2062                 if (testTypeParam.value == TestType::MsaaSampleMask && sampleCountParam.value == VK_SAMPLE_COUNT_1_BIT)
2063                 {
2064                     // SampleMask test requires MSAA
2065                     continue;
2066                 }
2067                 if (isHelperClassTest(testTypeParam.value) && sampleCountParam.value != VK_SAMPLE_COUNT_1_BIT)
2068                 {
2069                     // HelperClass test designed for non msaa case
2070                     continue;
2071                 }
2072                 subGroup = new tcu::TestCaseGroup(testCtx, sampleCountParam.name);
2073                 testGroupStack.back()->addChild(subGroup);
2074                 testGroupStack.push_back(subGroup);
2075 
2076                 for (const BoolParam &multiDrawsParam : multiDrawsParams)
2077                 {
2078                     if (isHelperClassTest(testTypeParam.value) && multiDrawsParam.value)
2079                     {
2080                         // helper class 2 draws but works like single draw call
2081                         continue;
2082                     }
2083 
2084                     subGroup = new tcu::TestCaseGroup(testCtx, multiDrawsParam.name);
2085                     testGroupStack.back()->addChild(subGroup);
2086                     testGroupStack.push_back(subGroup);
2087 
2088                     for (const BoolParam &multiPatchParam : multiPatchParams)
2089                     {
2090                         if (!coherentParam.value && multiPatchParam.value) // cannot guarantee
2091                         {
2092                             continue;
2093                         }
2094                         if (isHelperClassTest(testTypeParam.value) && multiPatchParam.value)
2095                         {
2096                             // helper class works on single patch cases
2097                             continue;
2098                         }
2099 
2100                         subGroup = new tcu::TestCaseGroup(testCtx, multiPatchParam.name);
2101                         testGroupStack.back()->addChild(subGroup);
2102                         testGroupStack.push_back(subGroup);
2103 
2104                         for (VkFormat format : formats)
2105                         {
2106                             tcu::TestCaseGroup *curGroup = testGroupStack.back();
2107                             const bool hasDepth          = tcu::hasDepthComponent(mapVkFormat(format).order);
2108                             const bool hasStencil        = tcu::hasStencilComponent(mapVkFormat(format).order);
2109                             std::string name             = formatToName(format);
2110 
2111                             TestParam testParam              = {};
2112                             testParam.coherent               = coherentParam.value;
2113                             testParam.testType               = testTypeParam.value;
2114                             testParam.colorFormat            = VK_FORMAT_R32G32B32A32_UINT;
2115                             testParam.depthStencilFormat     = VK_FORMAT_D32_SFLOAT_S8_UINT;
2116                             testParam.m_sampleCount          = sampleCountParam.value;
2117                             testParam.multipleDrawCalls      = multiDrawsParam.value;
2118                             testParam.multiplePatchesPerDraw = multiPatchParam.value;
2119                             testParam.frameBufferSize        = kImageSize;
2120                             if (testTypeParam.value == TestType::Depth ||
2121                                 testTypeParam.value == TestType::HelperClassDepth)
2122                             {
2123                                 if (hasDepth)
2124                                 {
2125                                     testParam.depthStencilFormat = format;
2126                                     curGroup->addChild(new ShaderTileImageTestCase(testCtx, name, testParam));
2127                                 }
2128                             }
2129                             else if (testTypeParam.value == TestType::Stencil ||
2130                                      testTypeParam.value == TestType::HelperClassStencil)
2131                             {
2132                                 if (hasStencil)
2133                                 {
2134                                     testParam.depthStencilFormat = format;
2135                                     curGroup->addChild(new ShaderTileImageTestCase(testCtx, name, testParam));
2136                                 }
2137                             }
2138                             else
2139                             {
2140                                 if (!hasStencil && !hasDepth)
2141                                 {
2142                                     if (isHelperClassTest(testTypeParam.value) && isNormalizedColorFormat(format))
2143                                     {
2144                                         // reduce helper class test cases and complexities
2145                                         continue;
2146                                     }
2147 
2148                                     const uint32_t maxResultValue =
2149                                         (getDrawCallCount(&testParam) *
2150                                              getPatchesPerDrawCount(testParam.multiplePatchesPerDraw) *
2151                                              getColorAttachmentCount(testParam.testType) +
2152                                          getSampleCount(testParam.m_sampleCount));
2153                                     const tcu::IVec4 channelBitDepth =
2154                                         tcu::getTextureFormatBitDepth(mapVkFormat(format));
2155 
2156                                     // color output precision is less than test case.
2157                                     // ban the overflow problem.
2158                                     if (static_cast<uint32_t>(1 << (channelBitDepth.y() - 1)) > maxResultValue)
2159                                     {
2160                                         testParam.colorFormat = format;
2161                                         curGroup->addChild(new ShaderTileImageTestCase(testCtx, name, testParam));
2162                                     }
2163                                 }
2164                             }
2165                         } // formats
2166                         testGroupStack.pop_back();
2167                     } // multiPatchParams
2168                     testGroupStack.pop_back();
2169                 } // multiDrawsParams
2170                 testGroupStack.pop_back();
2171             } // sampleCountParams
2172             testGroupStack.pop_back();
2173         } // testTypeParams
2174         testGroupStack.pop_back();
2175     } // coherentParams
2176 }
2177 } // namespace
2178 // anonymous namespace
2179 
createShaderTileImageTests(tcu::TestContext & testCtx)2180 tcu::TestCaseGroup *createShaderTileImageTests(tcu::TestContext &testCtx)
2181 {
2182     /* Add the color tests */
2183     tcu::TestCaseGroup *gr = new tcu::TestCaseGroup(testCtx, "shader_tile_image");
2184     createShaderTileImageTestVariations(testCtx, gr);
2185 
2186     return gr;
2187 }
2188 
2189 } // namespace rasterization
2190 } // namespace vkt
2191