• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2021 The Khronos Group Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Fragment Shading Barycentric extention tests
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktFragmentShadingBarycentricTests.hpp"
25 
26 #include "deDefs.h"
27 #include "vkDefs.hpp"
28 #include "vktTestCase.hpp"
29 #include "vktTestGroupUtil.hpp"
30 #include "vkCmdUtil.hpp"
31 #include "vkObjUtil.hpp"
32 #include "vkBuilderUtil.hpp"
33 #include "vkBarrierUtil.hpp"
34 #include "vkBufferWithMemory.hpp"
35 #include "vkImageWithMemory.hpp"
36 #include "vkTypeUtil.hpp"
37 #include "vkImageUtil.hpp"
38 #include "vkPipelineConstructionUtil.hpp"
39 
40 #include "tcuTestLog.hpp"
41 #include "tcuStringTemplate.hpp"
42 #include "tcuImageCompare.hpp"
43 #include "tcuVectorUtil.hpp"
44 
45 #include <cstdint>
46 #include <ostream>
47 #include <string>
48 #include <vector>
49 #include <map>
50 
51 namespace vkt
52 {
53 namespace FragmentShadingBarycentric
54 {
55 namespace
56 {
57 using namespace vk;
58 using namespace vkt;
59 
60 using de::MovePtr;
61 using std::map;
62 using std::string;
63 using std::vector;
64 using tcu::mix;
65 
66 enum TestType
67 {
68     TEST_TYPE_DATA = 0,
69     TEST_TYPE_WEIGHTS,
70 };
71 
72 enum TestSubtype
73 {
74     TEST_SUBTYPE_DEFAULT = 0,
75     TEST_SUBTYPE_MSAA_INTERPOLATE_AT_CENTROID,
76     TEST_SUBTYPE_MSAA_INTERPOLATE_AT_SAMPLE,
77     TEST_SUBTYPE_MSAA_INTERPOLATE_AT_OFFSET,
78     TEST_SUBTYPE_MSAA_CENTROID_QUALIFIER,
79     TEST_SUBTYPE_MSAA_SAMPLE_QUALIFIER,
80     TEST_SUBTYPE_PERVERTEX_CORRECTNESS,
81     TEST_SUBTYPE_TESS_SHADER,
82     TEST_SUBTYPE_GEOMETRY_SHADER,
83     TEST_SUBTYPE_TESSGEOM_SHADER,
84 };
85 
getShaderComboName(uint32_t testSubType)86 const char *getShaderComboName(uint32_t testSubType)
87 {
88     uint32_t idx = testSubType - TEST_SUBTYPE_TESS_SHADER;
89 
90     DE_ASSERT(idx < 3);
91 
92     static const char *sc_names[] = {
93         "with_tess_shader",
94         "with_geom_shader",
95         "with_tess_geom_shader",
96     };
97 
98     return sc_names[idx];
99 }
100 
101 const size_t DATA_TEST_WIDTH    = 8u;
102 const size_t DATA_TEST_HEIGHT   = 8u;
103 const size_t WEIGHT_TEST_WIDTH  = 128u;
104 const size_t WEIGHT_TEST_HEIGHT = 128u;
105 const float WEIGHT_TEST_SLOPE   = 16.0f;
106 
107 struct TestParams
108 {
109     const PipelineConstructionType pipelineConstructionType;
110     TestType testType;
111     TestSubtype testSubtype;
112     VkPrimitiveTopology topology;
113     bool dynamicIndexing;
114     size_t aggregate; // 0: value itself, 1:struct, 2+:Array
115     glu::DataType dataType;
116     size_t width;
117     size_t height;
118     bool perspective;
119     bool provokingVertexLast;
120     uint32_t rotation;
121     bool dynamicTopologyInPipeline;
122     VkSampleCountFlagBits sampleCount;
123     bool testWithInterpolation;
124     bool testWithFlatInterpolation;
125     bool clipVertices;
126     bool useMeshShader;
127 };
128 
getComponentCount(const TestParams & testParams)129 size_t getComponentCount(const TestParams &testParams)
130 {
131     const size_t scalarSize    = static_cast<size_t>(getDataTypeScalarSize(testParams.dataType));
132     const size_t aggregateSize = (testParams.aggregate > 0) ? testParams.aggregate : 1;
133     const size_t topologySize =
134         3; // Test always check three items in array: "Reads of per-vertex values for missing vertices, such as the third vertex of a line primitive, will return zero."
135     const size_t result = scalarSize * aggregateSize * topologySize;
136 
137     return result;
138 }
139 
makeImageCreateInfo(const VkFormat format,const uint32_t width,uint32_t height,VkSampleCountFlagBits samples)140 static VkImageCreateInfo makeImageCreateInfo(const VkFormat format, const uint32_t width, uint32_t height,
141                                              VkSampleCountFlagBits samples)
142 {
143     const VkImageUsageFlags usage =
144         VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
145     const VkImageCreateInfo imageCreateInfo = {
146         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
147         nullptr,                             // const void* pNext;
148         0u,                                  // VkImageCreateFlags flags;
149         VK_IMAGE_TYPE_2D,                    // VkImageType imageType;
150         format,                              // VkFormat format;
151         makeExtent3D(width, height, 1u),     // VkExtent3D extent;
152         1u,                                  // uint32_t mipLevels;
153         1u,                                  // uint32_t arrayLayers;
154         samples,                             // VkSampleCountFlagBits samples;
155         VK_IMAGE_TILING_OPTIMAL,             // VkImageTiling tiling;
156         usage,                               // VkImageUsageFlags usage;
157         VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode sharingMode;
158         0u,                                  // uint32_t queueFamilyIndexCount;
159         nullptr,                             // const uint32_t* pQueueFamilyIndices;
160         VK_IMAGE_LAYOUT_UNDEFINED,           // VkImageLayout initialLayout;
161     };
162 
163     return imageCreateInfo;
164 }
165 
makeRenderPass(const DeviceInterface & vk,const VkDevice device,const VkFormat format,VkSampleCountFlagBits samples)166 static Move<VkRenderPass> makeRenderPass(const DeviceInterface &vk, const VkDevice device, const VkFormat format,
167                                          VkSampleCountFlagBits samples)
168 {
169     const VkAttachmentDescription attachmentSingleSampleDesc{
170         (VkAttachmentDescriptionFlags)0u,        // VkAttachmentDescriptionFlags flags;
171         format,                                  // VkFormat format;
172         VK_SAMPLE_COUNT_1_BIT,                   // VkSampleCountFlagBits samples;
173         VK_ATTACHMENT_LOAD_OP_CLEAR,             // VkAttachmentLoadOp loadOp;
174         VK_ATTACHMENT_STORE_OP_STORE,            // VkAttachmentStoreOp storeOp;
175         VK_ATTACHMENT_LOAD_OP_DONT_CARE,         // VkAttachmentLoadOp stencilLoadOp;
176         VK_ATTACHMENT_STORE_OP_DONT_CARE,        // VkAttachmentStoreOp stencilStoreOp;
177         VK_IMAGE_LAYOUT_UNDEFINED,               // VkImageLayout initialLayout;
178         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout;
179     };
180 
181     const VkAttachmentDescription attachmentMultiSampleDesc{
182         (VkAttachmentDescriptionFlags)0u,        // VkAttachmentDescriptionFlags flags;
183         format,                                  // VkFormat format;
184         samples,                                 // VkSampleCountFlagBits samples;
185         VK_ATTACHMENT_LOAD_OP_CLEAR,             // VkAttachmentLoadOp loadOp;
186         VK_ATTACHMENT_STORE_OP_STORE,            // VkAttachmentStoreOp storeOp;
187         VK_ATTACHMENT_LOAD_OP_DONT_CARE,         // VkAttachmentLoadOp stencilLoadOp;
188         VK_ATTACHMENT_STORE_OP_DONT_CARE,        // VkAttachmentStoreOp stencilStoreOp;
189         VK_IMAGE_LAYOUT_UNDEFINED,               // VkImageLayout initialLayout;
190         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout;
191     };
192 
193     const VkAttachmentDescription attachments[] = {attachmentSingleSampleDesc, attachmentMultiSampleDesc};
194 
195     const VkAttachmentReference attachmentSingleSampleRef{
196         0u,                                      // uint32_t attachment;
197         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
198     };
199 
200     const VkAttachmentReference attachmentMultiSampleRef{
201         1u,                                      // uint32_t attachment;
202         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
203     };
204 
205     const bool useMultisampling = (samples > VK_SAMPLE_COUNT_1_BIT);
206     const VkAttachmentReference *colorAttachment =
207         useMultisampling ? &attachmentMultiSampleRef : &attachmentSingleSampleRef;
208     const VkAttachmentReference *resolveAttachment = useMultisampling ? &attachmentSingleSampleRef : nullptr;
209 
210     const VkSubpassDescription subpassDescription{
211         (VkSubpassDescriptionFlags)0u,   // VkSubpassDescriptionFlags flags;
212         VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
213         0u,                              // uint32_t inputAttachmentCount;
214         nullptr,                         // const VkAttachmentReference* pInputAttachments;
215         1u,                              // uint32_t colorAttachmentCount;
216         colorAttachment,                 // const VkAttachmentReference* pColorAttachments;
217         resolveAttachment,               // const VkAttachmentReference* pResolveAttachments;
218         nullptr,                         // const VkAttachmentReference* pDepthStencilAttachment;
219         0u,                              // uint32_t preserveAttachmentCount;
220         nullptr                          // const uint32_t* pPreserveAttachments;
221     };
222 
223     const VkRenderPassCreateInfo renderPassInfo{
224         VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
225         nullptr,                                   // const void* pNext;
226         (VkRenderPassCreateFlags)0u,               // VkRenderPassCreateFlags flags;
227         1u + useMultisampling,                     // uint32_t attachmentCount;
228         attachments,                               // const VkAttachmentDescription* pAttachments;
229         1u,                                        // uint32_t subpassCount;
230         &subpassDescription,                       // const VkSubpassDescription* pSubpasses;
231         0u,                                        // uint32_t dependencyCount;
232         nullptr                                    // const VkSubpassDependency* pDependencies;
233     };
234 
235     return createRenderPass(vk, device, &renderPassInfo, nullptr);
236 }
237 
238 using GraphicsPipelinePtr = std::unique_ptr<GraphicsPipelineWrapper>;
239 
makeGraphicsVertexShaderPipeline(PipelineConstructionType pipelineConstructionType,const InstanceInterface & vki,const DeviceInterface & vkd,const VkPhysicalDevice physicalDevice,const VkDevice device,const std::vector<std::string> & deviceExtensions,const PipelineLayoutWrapper & pipelineLayout,const VkRenderPass renderPass,const ShaderWrapper vertShaderModule,const ShaderWrapper fragShaderModule,const uint32_t width,const uint32_t height,const VkPrimitiveTopology topology,const VkSampleCountFlagBits rasterizationSamples,const bool withColor=false,const bool provokingVertexLast=false,const bool dynamicTopology=false,const ShaderWrapper tessCtrlShaderModule=ShaderWrapper (),const ShaderWrapper tessEvalShaderModule=ShaderWrapper (),const ShaderWrapper geometryShaderModule=ShaderWrapper ())240 static GraphicsPipelinePtr makeGraphicsVertexShaderPipeline(
241     PipelineConstructionType pipelineConstructionType, const InstanceInterface &vki, const DeviceInterface &vkd,
242     const VkPhysicalDevice physicalDevice, const VkDevice device, const std::vector<std::string> &deviceExtensions,
243     const PipelineLayoutWrapper &pipelineLayout, const VkRenderPass renderPass, const ShaderWrapper vertShaderModule,
244     const ShaderWrapper fragShaderModule, const uint32_t width, const uint32_t height,
245     const VkPrimitiveTopology topology, const VkSampleCountFlagBits rasterizationSamples, const bool withColor = false,
246     const bool provokingVertexLast = false, const bool dynamicTopology = false,
247     const ShaderWrapper tessCtrlShaderModule = ShaderWrapper(),
248     const ShaderWrapper tessEvalShaderModule = ShaderWrapper(),
249     const ShaderWrapper geometryShaderModule = ShaderWrapper())
250 {
251     const std::vector<VkViewport> viewports(1, makeViewport(width, height));
252     const std::vector<VkRect2D> scissors(1, makeRect2D(width, height));
253     const VkVertexInputBindingDescription vertexInputBindingDescription = {
254         0u,                          // uint32_t binding;
255         2 * sizeof(tcu::Vec4),       // uint32_t stride;
256         VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate;
257     };
258     const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] = {
259         {
260             0u,                            // uint32_t location;
261             0u,                            // uint32_t binding;
262             VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
263             0u                             // uint32_t offset;
264         },
265         {
266             1u,                            // uint32_t location;
267             0u,                            // uint32_t binding;
268             VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
269             sizeof(tcu::Vec4)              // uint32_t offset;
270         },
271     };
272     const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo = {
273         VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
274         nullptr,                                                   // const void* pNext;
275         (VkPipelineVertexInputStateCreateFlags)0,                  // VkPipelineVertexInputStateCreateFlags flags;
276         1u,                                                        // uint32_t vertexBindingDescriptionCount;
277         &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
278         DE_LENGTH_OF_ARRAY(vertexInputAttributeDescriptions), // uint32_t vertexAttributeDescriptionCount;
279         vertexInputAttributeDescriptions, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
280     };
281     const VkPipelineRasterizationProvokingVertexStateCreateInfoEXT provokingVertexStateCreateInfoEXT = {
282         VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_PROVOKING_VERTEX_STATE_CREATE_INFO_EXT, //  VkStructureType sType;
283         nullptr,                                                                         //  const void* pNext;
284         VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT, //  VkProvokingVertexModeEXT provokingVertexMode;
285     };
286     const VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo = {
287         VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,         //  VkStructureType sType;
288         provokingVertexLast ? &provokingVertexStateCreateInfoEXT : nullptr, //  const void* pNext;
289         0u,                              //  VkPipelineRasterizationStateCreateFlags flags;
290         VK_FALSE,                        //  VkBool32 depthClampEnable;
291         false,                           //  VkBool32 rasterizerDiscardEnable;
292         VK_POLYGON_MODE_FILL,            //  VkPolygonMode polygonMode;
293         VK_CULL_MODE_NONE,               //  VkCullModeFlags cullMode;
294         VK_FRONT_FACE_COUNTER_CLOCKWISE, //  VkFrontFace frontFace;
295         VK_FALSE,                        //  VkBool32 depthBiasEnable;
296         0.0f,                            //  float depthBiasConstantFactor;
297         0.0f,                            //  float depthBiasClamp;
298         0.0f,                            //  float depthBiasSlopeFactor;
299         1.0f                             //  float lineWidth;
300     };
301     const bool isMultiSample = (rasterizationSamples > VK_SAMPLE_COUNT_1_BIT);
302     const VkPipelineMultisampleStateCreateInfo multisampleStateInfo{
303         VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
304         nullptr,                                                  // const void* pNext;
305         0u,                                                       // VkPipelineMultisampleStateCreateFlags flags;
306         rasterizationSamples,                                     // VkSampleCountFlagBits rasterizationSamples;
307         (isMultiSample ? VK_TRUE : VK_FALSE),                     // VkBool32 sampleShadingEnable;
308         1.0f,                                                     // float minSampleShading;
309         nullptr,                                                  // const VkSampleMask* pSampleMask;
310         VK_FALSE,                                                 // VkBool32 alphaToCoverageEnable;
311         VK_FALSE,                                                 // VkBool32 alphaToOneEnable;
312     };
313     const VkDynamicState dynamicStates[] = {
314         VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY,
315     };
316     const VkPipelineDynamicStateCreateInfo dynamicStateCreateInfo = {
317         VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, //  VkStructureType sType;
318         nullptr,                                              //  const void* pNext;
319         0u,                                                   //  VkPipelineDynamicStateCreateFlags flags;
320         DE_LENGTH_OF_ARRAY(dynamicStates),                    //  uint32_t dynamicStateCount;
321         dynamicStates,                                        //  const VkDynamicState* pDynamicStates;
322     };
323     const VkPipelineDynamicStateCreateInfo *pDynamicStateCreateInfo =
324         dynamicTopology ? &dynamicStateCreateInfo : nullptr;
325     const auto pVertexInputStateCreateInfo = (withColor ? &vertexInputStateInfo : nullptr);
326 
327     GraphicsPipelinePtr pipelineWrapperPtr(
328         new GraphicsPipelineWrapper(vki, vkd, physicalDevice, device, deviceExtensions, pipelineConstructionType));
329     auto &pipelineWrapper = *pipelineWrapperPtr.get();
330 
331     pipelineWrapper.setMonolithicPipelineLayout(pipelineLayout)
332         .setDefaultDepthStencilState()
333         .setDefaultColorBlendState()
334         .setDefaultTopology(topology)
335         .setDynamicState(pDynamicStateCreateInfo)
336         .setupVertexInputState(pVertexInputStateCreateInfo)
337         .setupPreRasterizationShaderState(viewports, scissors, pipelineLayout, renderPass, 0u, vertShaderModule,
338                                           &rasterizationStateCreateInfo, tessCtrlShaderModule, tessEvalShaderModule,
339                                           geometryShaderModule)
340         .setupFragmentShaderState(pipelineLayout, renderPass, 0u, fragShaderModule, nullptr,
341                                   isMultiSample ? &multisampleStateInfo : nullptr)
342         .setupFragmentOutputState(renderPass, 0u, nullptr, &multisampleStateInfo)
343         .buildPipeline();
344 
345     return pipelineWrapperPtr;
346 }
347 
makeGraphicsMeshShaderPipeline(PipelineConstructionType pipelineConstructionType,const InstanceInterface & vki,const DeviceInterface & vkd,const VkPhysicalDevice physicalDevice,const VkDevice device,const std::vector<std::string> & deviceExtensions,const PipelineLayoutWrapper & pipelineLayout,const VkRenderPass renderPass,const ShaderWrapper meshShaderModule,const ShaderWrapper fragShaderModule,const uint32_t width,const uint32_t height,const VkPrimitiveTopology topology,const VkSampleCountFlagBits rasterizationSamples,const bool provokingVertexLast=false,const bool dynamicTopology=false)348 static GraphicsPipelinePtr makeGraphicsMeshShaderPipeline(
349     PipelineConstructionType pipelineConstructionType, const InstanceInterface &vki, const DeviceInterface &vkd,
350     const VkPhysicalDevice physicalDevice, const VkDevice device, const std::vector<std::string> &deviceExtensions,
351     const PipelineLayoutWrapper &pipelineLayout, const VkRenderPass renderPass, const ShaderWrapper meshShaderModule,
352     const ShaderWrapper fragShaderModule, const uint32_t width, const uint32_t height,
353     const VkPrimitiveTopology topology, const VkSampleCountFlagBits rasterizationSamples,
354     const bool provokingVertexLast = false, const bool dynamicTopology = false)
355 {
356     const std::vector<VkViewport> viewports(1, makeViewport(width, height));
357     const std::vector<VkRect2D> scissors(1, makeRect2D(width, height));
358 
359     const VkPipelineRasterizationProvokingVertexStateCreateInfoEXT provokingVertexStateCreateInfoEXT = {
360         VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_PROVOKING_VERTEX_STATE_CREATE_INFO_EXT, //  VkStructureType sType;
361         nullptr,                                                                         //  const void* pNext;
362         VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT, //  VkProvokingVertexModeEXT provokingVertexMode;
363     };
364     const VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo = {
365         VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,         //  VkStructureType sType;
366         provokingVertexLast ? &provokingVertexStateCreateInfoEXT : nullptr, //  const void* pNext;
367         0u,                              //  VkPipelineRasterizationStateCreateFlags flags;
368         VK_FALSE,                        //  VkBool32 depthClampEnable;
369         false,                           //  VkBool32 rasterizerDiscardEnable;
370         VK_POLYGON_MODE_FILL,            //  VkPolygonMode polygonMode;
371         VK_CULL_MODE_NONE,               //  VkCullModeFlags cullMode;
372         VK_FRONT_FACE_COUNTER_CLOCKWISE, //  VkFrontFace frontFace;
373         VK_FALSE,                        //  VkBool32 depthBiasEnable;
374         0.0f,                            //  float depthBiasConstantFactor;
375         0.0f,                            //  float depthBiasClamp;
376         0.0f,                            //  float depthBiasSlopeFactor;
377         1.0f                             //  float lineWidth;
378     };
379     const bool isMultiSample = (rasterizationSamples > VK_SAMPLE_COUNT_1_BIT);
380     const VkPipelineMultisampleStateCreateInfo multisampleStateInfo{
381         VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
382         nullptr,                                                  // const void* pNext;
383         0u,                                                       // VkPipelineMultisampleStateCreateFlags flags;
384         rasterizationSamples,                                     // VkSampleCountFlagBits rasterizationSamples;
385         (isMultiSample ? VK_TRUE : VK_FALSE),                     // VkBool32 sampleShadingEnable;
386         1.0f,                                                     // float minSampleShading;
387         nullptr,                                                  // const VkSampleMask* pSampleMask;
388         VK_FALSE,                                                 // VkBool32 alphaToCoverageEnable;
389         VK_FALSE,                                                 // VkBool32 alphaToOneEnable;
390     };
391     const VkDynamicState dynamicStates[] = {
392         VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY,
393     };
394     const VkPipelineDynamicStateCreateInfo dynamicStateCreateInfo = {
395         VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, //  VkStructureType sType;
396         nullptr,                                              //  const void* pNext;
397         0u,                                                   //  VkPipelineDynamicStateCreateFlags flags;
398         DE_LENGTH_OF_ARRAY(dynamicStates),                    //  uint32_t dynamicStateCount;
399         dynamicStates,                                        //  const VkDynamicState* pDynamicStates;
400     };
401     const VkPipelineDynamicStateCreateInfo *pDynamicStateCreateInfo =
402         dynamicTopology ? &dynamicStateCreateInfo : nullptr;
403 
404     GraphicsPipelinePtr pipelineWrapperPtr(
405         new GraphicsPipelineWrapper(vki, vkd, physicalDevice, device, deviceExtensions, pipelineConstructionType));
406     auto &pipelineWrapper = *pipelineWrapperPtr.get();
407 
408     pipelineWrapper.setMonolithicPipelineLayout(pipelineLayout)
409         .setDefaultDepthStencilState()
410         .setDefaultColorBlendState()
411         .setDefaultTopology(topology)
412         .setDynamicState(pDynamicStateCreateInfo)
413         .setupPreRasterizationMeshShaderState(viewports, scissors, pipelineLayout, renderPass, 0u, vk::ShaderWrapper(),
414                                               meshShaderModule, &rasterizationStateCreateInfo)
415         .setupFragmentShaderState(pipelineLayout, renderPass, 0u, fragShaderModule)
416         .setupFragmentOutputState(renderPass, 0u, nullptr, &multisampleStateInfo)
417         .buildPipeline();
418 
419     return pipelineWrapperPtr;
420 }
421 
makeGraphicsPipeline(bool useMeshShader,PipelineConstructionType pipelineConstructionType,const InstanceInterface & vki,const DeviceInterface & vkd,const VkPhysicalDevice physicalDevice,const VkDevice device,const std::vector<std::string> & deviceExtensions,const PipelineLayoutWrapper & pipelineLayout,const VkRenderPass renderPass,const ShaderWrapper vertOrMeshShaderModule,const ShaderWrapper fragShaderModule,const uint32_t width,const uint32_t height,const VkPrimitiveTopology topology,const VkSampleCountFlagBits rasterizationSamples,const bool withColor=false,const bool provokingVertexLast=false,const bool dynamicTopology=false,const ShaderWrapper tessCtrlShaderModule=ShaderWrapper (),const ShaderWrapper tessEvalShaderModule=ShaderWrapper (),const ShaderWrapper geometryShaderModule=ShaderWrapper ())422 static GraphicsPipelinePtr makeGraphicsPipeline(
423     bool useMeshShader, PipelineConstructionType pipelineConstructionType, const InstanceInterface &vki,
424     const DeviceInterface &vkd, const VkPhysicalDevice physicalDevice, const VkDevice device,
425     const std::vector<std::string> &deviceExtensions, const PipelineLayoutWrapper &pipelineLayout,
426     const VkRenderPass renderPass, const ShaderWrapper vertOrMeshShaderModule, const ShaderWrapper fragShaderModule,
427     const uint32_t width, const uint32_t height, const VkPrimitiveTopology topology,
428     const VkSampleCountFlagBits rasterizationSamples, const bool withColor = false,
429     const bool provokingVertexLast = false, const bool dynamicTopology = false,
430     const ShaderWrapper tessCtrlShaderModule = ShaderWrapper(),
431     const ShaderWrapper tessEvalShaderModule = ShaderWrapper(),
432     const ShaderWrapper geometryShaderModule = ShaderWrapper())
433 {
434     if (useMeshShader)
435     {
436         DE_ASSERT(!tessCtrlShaderModule.isSet());
437         DE_ASSERT(!tessEvalShaderModule.isSet());
438         DE_ASSERT(!geometryShaderModule.isSet());
439 
440         return makeGraphicsMeshShaderPipeline(pipelineConstructionType, vki, vkd, physicalDevice, device,
441                                               deviceExtensions, pipelineLayout, renderPass, vertOrMeshShaderModule,
442                                               fragShaderModule, width, height, topology, rasterizationSamples,
443                                               provokingVertexLast, dynamicTopology);
444     }
445     else
446     {
447         return makeGraphicsVertexShaderPipeline(
448             pipelineConstructionType, vki, vkd, physicalDevice, device, deviceExtensions, pipelineLayout, renderPass,
449             vertOrMeshShaderModule, fragShaderModule, width, height, topology, rasterizationSamples, withColor,
450             provokingVertexLast, dynamicTopology, tessCtrlShaderModule, tessEvalShaderModule, geometryShaderModule);
451     }
452 }
453 
454 // Function replacing all occurrences of substring with string passed in last parameter.
replace(const std::string & str,const std::string & from,const std::string & to)455 static inline std::string replace(const std::string &str, const std::string &from, const std::string &to)
456 {
457     std::string result(str);
458 
459     size_t start_pos = 0;
460     while ((start_pos = result.find(from, start_pos)) != std::string::npos)
461     {
462         result.replace(start_pos, from.length(), to);
463         start_pos += to.length();
464     }
465 
466     return result;
467 }
468 
469 class FragmentShadingBarycentricDataTestInstance : public TestInstance
470 {
471 public:
472     FragmentShadingBarycentricDataTestInstance(Context &context, const TestParams &testParams);
473     virtual ~FragmentShadingBarycentricDataTestInstance();
474     virtual tcu::TestStatus iterate(void);
475 
476 protected:
477     vector<tcu::Vec4> generateVertexBuffer(void);
478     MovePtr<BufferWithMemory> createVertexBuffer(const vector<tcu::Vec4> &vertices);
479     bool verify(BufferWithMemory *resultBuffer);
480     bool getProvokingVertexLast(void);
481 
482     TestParams m_testParams;
483 };
484 
FragmentShadingBarycentricDataTestInstance(Context & context,const TestParams & testParams)485 FragmentShadingBarycentricDataTestInstance::FragmentShadingBarycentricDataTestInstance(Context &context,
486                                                                                        const TestParams &testParams)
487     : TestInstance(context)
488     , m_testParams(testParams)
489 {
490 }
491 
~FragmentShadingBarycentricDataTestInstance()492 FragmentShadingBarycentricDataTestInstance::~FragmentShadingBarycentricDataTestInstance()
493 {
494 }
495 
generateVertexBuffer(void)496 vector<tcu::Vec4> FragmentShadingBarycentricDataTestInstance::generateVertexBuffer(void)
497 {
498     size_t verticesCount = static_cast<size_t>(~0ull);
499     vector<tcu::Vec4> result;
500 
501     DE_ASSERT(!m_testParams.clipVertices || m_testParams.topology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST);
502 
503     switch (m_testParams.topology)
504     {
505     case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
506     {
507         verticesCount = m_testParams.width * m_testParams.height;
508 
509         result.reserve(verticesCount);
510 
511         for (size_t y = 0; y < m_testParams.height; y++)
512         {
513             const float yy = -1.0f + 2.0f * ((0.5f + float(y)) / float(m_testParams.height));
514 
515             for (size_t x = 0; x < m_testParams.width; x++)
516             {
517                 const float xx = -1.0f + 2.0f * ((0.5f + float(x)) / float(m_testParams.width));
518 
519                 result.push_back(tcu::Vec4(xx, yy, 0.0f, 1.0f));
520             }
521         }
522 
523         break;
524     }
525 
526     case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
527     {
528         verticesCount = 2 * m_testParams.height;
529 
530         result.reserve(verticesCount);
531 
532         for (size_t y = 0; y < m_testParams.height; y++)
533         {
534             const float yy = -1.0f + 2.0f * ((0.5f + float(y)) / float(m_testParams.height));
535 
536             result.push_back(tcu::Vec4(-1.0f, yy, 0.0f, 1.0f));
537             result.push_back(tcu::Vec4(1.0f, yy, 0.0f, 1.0f));
538         }
539 
540         break;
541     }
542 
543     case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
544     {
545         verticesCount = 2 * m_testParams.height;
546 
547         result.reserve(verticesCount);
548 
549         for (size_t y = 0; y < m_testParams.height; y++)
550         {
551             const float yy = -1.0f + 2.0f * (0.5f + float(y)) / float(m_testParams.height);
552             ;
553 
554             if (y % 2 == 0)
555             {
556                 result.push_back(tcu::Vec4(-2.0f, yy, 0.0f, 1.0f));
557                 result.push_back(tcu::Vec4(+2.0f, yy, 0.0f, 1.0f));
558             }
559             else
560             {
561                 result.push_back(tcu::Vec4(+2.0f, yy, 0.0f, 1.0f));
562                 result.push_back(tcu::Vec4(-2.0f, yy, 0.0f, 1.0f));
563             }
564         }
565 
566         break;
567     }
568 
569     case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST:
570     case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
571     {
572         verticesCount = 6;
573 
574         result.reserve(verticesCount);
575 
576         result.push_back(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
577         result.push_back(tcu::Vec4(-1.0f, +1.0f, 0.0f, 1.0f));
578         result.push_back(tcu::Vec4(+1.0f, +1.0f, 0.0f, 1.0f));
579 
580         result.push_back(tcu::Vec4(+1.0f, +1.0f, 0.0f, 1.0f));
581         result.push_back(tcu::Vec4(+1.0f, -1.0f, 0.0f, 1.0f));
582         result.push_back(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
583 
584         break;
585     }
586 
587     case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
588     {
589         verticesCount = 4;
590 
591         result.reserve(verticesCount);
592 
593         result.push_back(tcu::Vec4(-1.0f, +1.0f, 0.0f, 1.0f));
594         result.push_back(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
595         result.push_back(tcu::Vec4(+1.0f, +1.0f, 0.0f, 1.0f));
596         result.push_back(tcu::Vec4(+1.0f, -1.0f, 0.0f, 1.0f));
597 
598         break;
599     }
600 
601     case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
602     {
603         verticesCount = 4;
604 
605         result.reserve(verticesCount);
606 
607         result.push_back(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
608         result.push_back(tcu::Vec4(-1.0f, +1.0f, 0.0f, 1.0f));
609         result.push_back(tcu::Vec4(+1.0f, +1.0f, 0.0f, 1.0f));
610         result.push_back(tcu::Vec4(+1.0f, -1.0f, 0.0f, 1.0f));
611 
612         break;
613     }
614 
615     case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
616     {
617         verticesCount = 4 * m_testParams.height;
618 
619         result.reserve(verticesCount);
620 
621         for (size_t y = 0; y < m_testParams.height; y++)
622         {
623             const float yy = -1.0f + 2.0f * ((0.5f + float(y)) / float(m_testParams.height));
624 
625             result.push_back(tcu::Vec4(-2.0f, yy, 0.0f, 1.0f));
626             result.push_back(tcu::Vec4(-1.0f, yy, 0.0f, 1.0f));
627             result.push_back(tcu::Vec4(1.0f, yy, 0.0f, 1.0f));
628             result.push_back(tcu::Vec4(2.0f, yy, 0.0f, 1.0f));
629         }
630 
631         break;
632     }
633 
634     case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
635     {
636         verticesCount = 2 * m_testParams.height + 2;
637 
638         result.reserve(verticesCount);
639 
640         result.push_back(tcu::Vec4(-10.0f, -10.0f, 0.0f, 1.0f));
641 
642         for (size_t y = 0; y < m_testParams.height; y++)
643         {
644             const float ky = (0.5f + float(y)) / float(m_testParams.height);
645             const float yy = -1.0f + 2.0f * ky;
646 
647             if (y % 2 == 0)
648             {
649                 result.push_back(tcu::Vec4(-2.0f, yy, 0.0f, 1.0f));
650                 result.push_back(tcu::Vec4(+2.0f, yy, 0.0f, 1.0f));
651             }
652             else
653             {
654                 result.push_back(tcu::Vec4(+2.0f, yy, 0.0f, 1.0f));
655                 result.push_back(tcu::Vec4(-2.0f, yy, 0.0f, 1.0f));
656             }
657         }
658 
659         result.push_back(tcu::Vec4(+10.0f, +10.0f, 0.0f, 1.0f));
660 
661         break;
662     }
663 
664     case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
665     {
666         verticesCount = 12;
667 
668         result.reserve(verticesCount);
669 
670         result.push_back(tcu::Vec4(-1.0f, +1.0f, 0.0f, 1.0f));
671         result.push_back(tcu::Vec4(+1.0f, +3.0f, 0.0f, 1.0f));
672         result.push_back(tcu::Vec4(+1.0f, +1.0f, 0.0f, 1.0f));
673         result.push_back(tcu::Vec4(+1.0f, -1.0f, 0.0f, 1.0f));
674         result.push_back(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
675         result.push_back(tcu::Vec4(-3.0f, -1.0f, 0.0f, 1.0f));
676 
677         result.push_back(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
678         result.push_back(tcu::Vec4(-1.0f, +1.0f, 0.0f, 1.0f));
679         result.push_back(tcu::Vec4(+1.0f, +1.0f, 0.0f, 1.0f));
680         result.push_back(tcu::Vec4(+3.0f, +1.0f, 0.0f, 1.0f));
681         result.push_back(tcu::Vec4(+1.0f, -1.0f, 0.0f, 1.0f));
682         result.push_back(tcu::Vec4(-1.0f, -3.0f, 0.0f, 1.0f));
683 
684         break;
685     }
686 
687     case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
688     {
689         verticesCount = 8;
690 
691         result.reserve(verticesCount);
692 
693         result.push_back(tcu::Vec4(-1.0f, +1.0f, 0.0f, 1.0f));
694         result.push_back(tcu::Vec4(+1.0f, +3.0f, 0.0f, 1.0f));
695         result.push_back(tcu::Vec4(+1.0f, +1.0f, 0.0f, 1.0f));
696         result.push_back(tcu::Vec4(-3.0f, -1.0f, 0.0f, 1.0f));
697         result.push_back(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
698         result.push_back(tcu::Vec4(+3.0f, +1.0f, 0.0f, 1.0f));
699         result.push_back(tcu::Vec4(+1.0f, -1.0f, 0.0f, 1.0f));
700         result.push_back(tcu::Vec4(-1.0f, -3.0f, 0.0f, 1.0f));
701 
702         break;
703     }
704 
705     default:
706         TCU_THROW(InternalError, "Unknown topology");
707     }
708 
709     DE_ASSERT(result.size() == verticesCount);
710 
711     if (m_testParams.clipVertices)
712     {
713         for (size_t i = 0; i < result.size(); ++i)
714         {
715             result[i][1] *= 2.0f;
716         }
717     }
718 
719     return result;
720 }
721 
verify(BufferWithMemory * resultBuffer)722 bool FragmentShadingBarycentricDataTestInstance::verify(BufferWithMemory *resultBuffer)
723 {
724     const size_t components             = getComponentCount(m_testParams);
725     const uint32_t expectedPerVertex    = static_cast<uint32_t>(1 << components) - 1;
726     const uint32_t expectedInterpolated = (static_cast<uint32_t>(1 << components / 3) - 1);
727     const uint32_t expectedFlat         = (static_cast<uint32_t>(1 << components / 3) - 1);
728     const tcu::UVec4 expected =
729         m_testParams.testSubtype == TEST_SUBTYPE_PERVERTEX_CORRECTNESS ?
730             tcu::UVec4(10u) :
731             tcu::UVec4(expectedPerVertex, m_testParams.testWithInterpolation ? expectedInterpolated : 0u,
732                        m_testParams.testWithFlatInterpolation ? expectedFlat : 0u, 0u);
733     const tcu::UVec4 *retrieved = (tcu::UVec4 *)resultBuffer->getAllocation().getHostPtr();
734     size_t failures             = 0;
735 
736     {
737         size_t n = 0;
738 
739         for (size_t y = 0; y < m_testParams.height; y++)
740             for (size_t x = 0; x < m_testParams.width; x++)
741             {
742                 if (retrieved[n] != expected)
743                     failures++;
744 
745                 n++;
746             }
747     }
748 
749     if (failures)
750     {
751         const uint8_t places = static_cast<uint8_t>(components / 4);
752         tcu::TestLog &log    = m_context.getTestContext().getLog();
753         size_t n             = 0;
754         std::ostringstream s;
755 
756         s << "Expected mask:" << std::setfill('0') << std::hex << std::setw(places) << expected << std::endl;
757 
758         for (size_t y = 0; y < m_testParams.height; y++)
759         {
760             for (size_t x = 0; x < m_testParams.width; x++)
761             {
762                 s << std::setw(places) << retrieved[n] << ' ';
763 
764                 n++;
765             }
766 
767             s << std::endl;
768         }
769 
770         log << tcu::TestLog::Message << s.str() << tcu::TestLog::EndMessage;
771     }
772 
773     return failures == 0;
774 }
775 
createVertexBuffer(const vector<tcu::Vec4> & vertices)776 MovePtr<BufferWithMemory> FragmentShadingBarycentricDataTestInstance::createVertexBuffer(
777     const vector<tcu::Vec4> &vertices)
778 {
779     const DeviceInterface &vkd          = m_context.getDeviceInterface();
780     const VkDevice device               = m_context.getDevice();
781     Allocator &allocator                = m_context.getDefaultAllocator();
782     const VkDeviceSize vertexBufferSize = vertices.size() * sizeof(vertices[0]);
783     const VkBufferCreateInfo vertexBufferCreateInfo =
784         makeBufferCreateInfo(vertexBufferSize, m_testParams.useMeshShader ? VK_BUFFER_USAGE_STORAGE_BUFFER_BIT :
785                                                                             VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
786     MovePtr<BufferWithMemory> vertexBuffer = MovePtr<BufferWithMemory>(
787         new BufferWithMemory(vkd, device, allocator, vertexBufferCreateInfo, MemoryRequirement::HostVisible));
788     Allocation &vertexBufferAlloc = vertexBuffer->getAllocation();
789 
790     // Initialize vertex data
791     deMemcpy(vertexBufferAlloc.getHostPtr(), vertices.data(), (size_t)vertexBufferSize);
792     flushAlloc(vkd, device, vertexBufferAlloc);
793 
794     return vertexBuffer;
795 }
796 
getProvokingVertexLast(void)797 bool FragmentShadingBarycentricDataTestInstance::getProvokingVertexLast(void)
798 {
799     if (m_testParams.provokingVertexLast && m_testParams.topology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP)
800     {
801         const VkPhysicalDeviceFragmentShaderBarycentricPropertiesKHR &fragmentShaderBarycentricProperties =
802             m_context.getFragmentShaderBarycentricProperties();
803 
804         if (fragmentShaderBarycentricProperties.triStripVertexOrderIndependentOfProvokingVertex)
805             return false;
806     }
807 
808     return m_testParams.provokingVertexLast;
809 }
810 
iterate(void)811 tcu::TestStatus FragmentShadingBarycentricDataTestInstance::iterate(void)
812 {
813     const InstanceInterface &vki          = m_context.getInstanceInterface();
814     const DeviceInterface &vkd            = m_context.getDeviceInterface();
815     const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
816     const VkDevice device                 = m_context.getDevice();
817     const auto &deviceExtensions          = m_context.getDeviceExtensions();
818     const VkQueue queue                   = m_context.getUniversalQueue();
819     Allocator &allocator                  = m_context.getDefaultAllocator();
820     const uint32_t queueFamilyIndex       = m_context.getUniversalQueueFamilyIndex();
821 
822     const VkDeviceSize offsetZero      = 0ull;
823     const VkFormat format              = VK_FORMAT_R32G32B32A32_UINT;
824     const uint32_t pixelSize           = mapVkFormat(format).getPixelSize();
825     const tcu::Vec4 clearColor         = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
826     const uint32_t width               = static_cast<uint32_t>(m_testParams.width);
827     const uint32_t height              = static_cast<uint32_t>(m_testParams.height);
828     const VkPrimitiveTopology topology = m_testParams.topology;
829     const bool withColor               = false;
830     const bool provokingVertexLast     = getProvokingVertexLast();
831 
832     const vector<tcu::Vec4> vertices       = generateVertexBuffer();
833     const uint32_t vertexCount             = static_cast<uint32_t>(vertices.size());
834     MovePtr<BufferWithMemory> vertexBuffer = createVertexBuffer(vertices);
835 
836     const VkImageCreateInfo imageCreateInfo = makeImageCreateInfo(format, width, height, VK_SAMPLE_COUNT_1_BIT);
837     const VkImageSubresourceRange imageSubresourceRange =
838         makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
839     const MovePtr<ImageWithMemory> image =
840         MovePtr<ImageWithMemory>(new ImageWithMemory(vkd, device, allocator, imageCreateInfo, MemoryRequirement::Any));
841     const Move<VkImageView> imageView =
842         makeImageView(vkd, device, **image, VK_IMAGE_VIEW_TYPE_2D, format, imageSubresourceRange);
843 
844     bool useMeshShader = m_testParams.useMeshShader;
845 
846     const VkBufferCreateInfo resultBufferCreateInfo =
847         makeBufferCreateInfo(width * height * pixelSize,
848                              (useMeshShader ? VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT :
849                                               VK_BUFFER_USAGE_TRANSFER_DST_BIT));
850     MovePtr<BufferWithMemory> resultBuffer = MovePtr<BufferWithMemory>(
851         new BufferWithMemory(vkd, device, allocator, resultBufferCreateInfo, MemoryRequirement::HostVisible));
852 
853     const string shaderSuffix  = (provokingVertexLast == m_testParams.provokingVertexLast) ? "" : "-forced";
854     const ShaderWrapper module = ShaderWrapper(
855         vkd, device, m_context.getBinaryCollection().get(useMeshShader ? "mesh" + shaderSuffix : "vert" + shaderSuffix),
856         0u);
857 
858     const ShaderWrapper tessCtrlShaderModule =
859         ((m_testParams.testSubtype == TEST_SUBTYPE_TESS_SHADER) ||
860          (m_testParams.testSubtype == TEST_SUBTYPE_TESSGEOM_SHADER)) ?
861             ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("tess_ctrl" + shaderSuffix), 0u) :
862             ShaderWrapper();
863     const ShaderWrapper tessEvalShaderModule =
864         ((m_testParams.testSubtype == TEST_SUBTYPE_TESS_SHADER) ||
865          (m_testParams.testSubtype == TEST_SUBTYPE_TESSGEOM_SHADER)) ?
866             ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("tess_eval" + shaderSuffix), 0u) :
867             ShaderWrapper();
868     const ShaderWrapper geometryShaderModule =
869         ((m_testParams.testSubtype == TEST_SUBTYPE_GEOMETRY_SHADER) ||
870          (m_testParams.testSubtype == TEST_SUBTYPE_TESSGEOM_SHADER)) ?
871             ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("geom" + shaderSuffix), 0u) :
872             ShaderWrapper();
873     const ShaderWrapper fragModule =
874         ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("frag" + shaderSuffix), 0u);
875     RenderPassWrapper renderPass = RenderPassWrapper(m_testParams.pipelineConstructionType, vkd, device, format);
876     renderPass.createFramebuffer(vkd, device, **image, *imageView, width, height);
877     const uint32_t pushConstants[] = {0, 1, 2};
878     const VkPushConstantRange pushConstantRange =
879         makePushConstantRange(VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(pushConstants));
880     const VkPushConstantRange *pushConstantRangePtr = m_testParams.dynamicIndexing ? &pushConstantRange : nullptr;
881     const uint32_t pushConstantRangeCount           = m_testParams.dynamicIndexing ? 1 : 0;
882     const Move<VkCommandPool> commandPool           = createCommandPool(vkd, device, 0, queueFamilyIndex);
883     const Move<VkCommandBuffer> commandBuffer =
884         allocateCommandBuffer(vkd, device, *commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
885     Move<VkDescriptorSetLayout> descriptorSetLayout;
886     Move<VkDescriptorPool> descriptorPool;
887     Move<VkDescriptorSet> descriptorSet;
888 
889     if (useMeshShader)
890     {
891         DescriptorSetLayoutBuilder layoutBuilder;
892         layoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_MESH_BIT_EXT);
893         descriptorSetLayout = layoutBuilder.build(vkd, device);
894 
895         DescriptorPoolBuilder poolBuilder;
896         poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
897         descriptorPool = poolBuilder.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
898 
899         descriptorSet = makeDescriptorSet(vkd, device, descriptorPool.get(), *descriptorSetLayout);
900     }
901 
902     // Pipeline layout
903     const PipelineLayoutWrapper pipelineLayout(m_testParams.pipelineConstructionType, vkd, device,
904                                                useMeshShader ? 1 : 0, useMeshShader ? &*descriptorSetLayout : nullptr,
905                                                pushConstantRangeCount, pushConstantRangePtr);
906     const auto pipelineWrapper =
907         makeGraphicsPipeline(m_testParams.useMeshShader, m_testParams.pipelineConstructionType, vki, vkd,
908                              physicalDevice, device, deviceExtensions, pipelineLayout, *renderPass, module, fragModule,
909                              width, height, topology, VK_SAMPLE_COUNT_1_BIT, withColor, provokingVertexLast, false,
910                              tessCtrlShaderModule, tessEvalShaderModule, geometryShaderModule);
911 
912     // Update descriptor set.
913     if (useMeshShader)
914     {
915         DescriptorSetUpdateBuilder updateBuilder;
916 
917         const auto vertexBufferSize     = static_cast<VkDeviceSize>(de::dataSize(vertices));
918         const auto vertexBufferDescInfo = makeDescriptorBufferInfo(vertexBuffer->get(), 0ull, vertexBufferSize);
919         updateBuilder.writeSingle(descriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(0u),
920                                   VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &vertexBufferDescInfo);
921         updateBuilder.update(vkd, device);
922     }
923 
924     const tcu::IVec3 groupCount =
925         (topology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST) ? tcu::IVec3(4u, 4u, 4u) : tcu::IVec3(1u, 1u, 1u);
926 
927     beginCommandBuffer(vkd, *commandBuffer);
928     {
929         renderPass.begin(vkd, *commandBuffer, makeRect2D(width, height), clearColor);
930 
931         pipelineWrapper->bind(*commandBuffer);
932 
933         if (useMeshShader)
934             vkd.cmdBindDescriptorSets(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0u, 1u,
935                                       &descriptorSet.get(), 0u, nullptr);
936         else
937             vkd.cmdBindVertexBuffers(*commandBuffer, 0u, 1u, &vertexBuffer->get(), &offsetZero);
938 
939         if (m_testParams.dynamicIndexing)
940             vkd.cmdPushConstants(*commandBuffer, *pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0u,
941                                  sizeof(pushConstants), &pushConstants);
942 
943         if (useMeshShader)
944             vkd.cmdDrawMeshTasksEXT(*commandBuffer, groupCount.x(), groupCount.y(), groupCount.z());
945         else
946             vkd.cmdDraw(*commandBuffer, vertexCount, 1u, 0u, 0u);
947 
948         renderPass.end(vkd, *commandBuffer);
949 
950         copyImageToBuffer(vkd, *commandBuffer, image->get(), resultBuffer->get(), tcu::IVec2(width, height));
951     }
952 
953     endCommandBuffer(vkd, *commandBuffer);
954     submitCommandsAndWait(vkd, device, queue, *commandBuffer);
955 
956     invalidateMappedMemoryRange(vkd, device, resultBuffer->getAllocation().getMemory(),
957                                 resultBuffer->getAllocation().getOffset(), VK_WHOLE_SIZE);
958 
959     DE_ASSERT(8 * pixelSize >= 3 * getComponentCount(m_testParams));
960 
961     if (verify(resultBuffer.get()))
962         return tcu::TestStatus::pass("Pass");
963     else
964         return tcu::TestStatus::fail("Fail");
965 }
966 
967 class FragmentShadingBarycentricWeightTestInstance : public TestInstance
968 {
969 public:
970     FragmentShadingBarycentricWeightTestInstance(Context &context, const TestParams &testParams);
971     virtual ~FragmentShadingBarycentricWeightTestInstance();
972     virtual tcu::TestStatus iterate(void);
973 
974 protected:
975     void addVertexWithColor(vector<tcu::Vec4> &vertices, const tcu::Vec4 &vertex, const tcu::Vec4 &color);
976     vector<tcu::Vec4> generateVertexBuffer(void);
977     MovePtr<BufferWithMemory> createVertexBuffer(const vector<tcu::Vec4> &vertices);
978     bool verify(VkFormat format, BufferWithMemory *referenceBuffer, BufferWithMemory *resultBuffer);
979 
980     TestParams m_testParams;
981 };
982 
FragmentShadingBarycentricWeightTestInstance(Context & context,const TestParams & testParams)983 FragmentShadingBarycentricWeightTestInstance::FragmentShadingBarycentricWeightTestInstance(Context &context,
984                                                                                            const TestParams &testParams)
985     : TestInstance(context)
986     , m_testParams(testParams)
987 {
988 }
989 
~FragmentShadingBarycentricWeightTestInstance()990 FragmentShadingBarycentricWeightTestInstance::~FragmentShadingBarycentricWeightTestInstance()
991 {
992 }
993 
addVertexWithColor(vector<tcu::Vec4> & vertices,const tcu::Vec4 & vertex,const tcu::Vec4 & color)994 void FragmentShadingBarycentricWeightTestInstance::addVertexWithColor(vector<tcu::Vec4> &vertices,
995                                                                       const tcu::Vec4 &vertex, const tcu::Vec4 &color)
996 {
997     vertices.push_back(vertex);
998     vertices.push_back(color);
999 }
1000 
generateVertexBuffer(void)1001 vector<tcu::Vec4> FragmentShadingBarycentricWeightTestInstance::generateVertexBuffer(void)
1002 {
1003     const float slope             = WEIGHT_TEST_SLOPE;
1004     const tcu::Vec4 leftBotColor  = tcu::Vec4(0.00f, 0.00f, 0.00f, 1.0f);
1005     const tcu::Vec4 leftTopColor  = tcu::Vec4(1.00f, 0.00f, 0.00f, 1.0f);
1006     const tcu::Vec4 rightTopColor = tcu::Vec4(0.00f, 1.00f, 0.00f, 1.0f);
1007     const tcu::Vec4 rightBotColor = tcu::Vec4(0.00f, 0.00f, 1.00f, 1.0f);
1008     const tcu::Vec4 noneColor     = tcu::Vec4(0.25f, 0.50f, 0.75f, 1.0f);
1009     size_t vertexCount            = static_cast<size_t>(~0ull);
1010     vector<tcu::Vec4> result;
1011 
1012     DE_ASSERT(slope >= 1.0f);
1013 
1014     switch (m_testParams.topology)
1015     {
1016     case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
1017     {
1018         vertexCount = m_testParams.width * m_testParams.height;
1019 
1020         result.reserve(2 * vertexCount);
1021 
1022         for (size_t y = 0; y < m_testParams.height; y++)
1023         {
1024             const float ky             = (0.5f + float(y)) / float(m_testParams.height);
1025             const float yy             = -1.0f + 2.0f * ky;
1026             const tcu::Vec4 leftColor  = mix(leftTopColor, leftBotColor, ky);
1027             const tcu::Vec4 rightColor = mix(rightTopColor, rightBotColor, ky);
1028 
1029             for (size_t x = 0; x < m_testParams.width; x++)
1030             {
1031                 const float kx         = (0.5f + float(x)) / float(m_testParams.width);
1032                 const float xx         = -1.0f + 2.0f * kx;
1033                 const float pointSlope = 1.0f + kx * (slope - 1.0f);
1034                 const tcu::Vec4 point  = tcu::Vec4(xx, yy, 0.0f, 1.0f) * pointSlope;
1035                 const tcu::Vec4 color  = mix(leftColor, rightColor, kx);
1036 
1037                 addVertexWithColor(result, point, color);
1038             }
1039         }
1040 
1041         break;
1042     }
1043 
1044     case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
1045     {
1046         vertexCount = 2 * m_testParams.height;
1047 
1048         result.reserve(2 * vertexCount);
1049 
1050         for (size_t y = 0; y < m_testParams.height; y++)
1051         {
1052             const float ky             = (0.5f + float(y)) / float(m_testParams.height);
1053             const float yy             = -1.0f + 2.0f * ky;
1054             const tcu::Vec4 leftColor  = mix(leftTopColor, leftBotColor, ky);
1055             const tcu::Vec4 rightColor = mix(rightTopColor, rightBotColor, ky);
1056             const tcu::Vec4 left       = tcu::Vec4(-1.0f, yy, 0.0f, 1.0f);
1057             const tcu::Vec4 right      = tcu::Vec4(1.0f, yy, 0.0f, 1.0f) * slope;
1058 
1059             addVertexWithColor(result, left, leftColor);
1060             addVertexWithColor(result, right, rightColor);
1061         }
1062 
1063         break;
1064     }
1065 
1066     case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
1067     {
1068         vertexCount = 2 * m_testParams.height;
1069 
1070         result.reserve(2 * vertexCount);
1071 
1072         for (size_t y = 0; y < m_testParams.height; y++)
1073         {
1074             const float ky             = (0.5f + float(y)) / float(m_testParams.height);
1075             const float yy             = -1.0f + 2.0f * ky;
1076             const tcu::Vec4 leftColor  = mix(leftTopColor, leftBotColor, ky);
1077             const tcu::Vec4 rightColor = mix(rightTopColor, rightBotColor, ky);
1078             const tcu::Vec4 left       = tcu::Vec4(-2.0f, yy, 0.0f, 1.0f);
1079             const tcu::Vec4 right      = tcu::Vec4(2.0f, yy, 0.0f, 1.0f) * slope;
1080 
1081             if (y % 2 == 0)
1082             {
1083                 addVertexWithColor(result, left, leftColor);
1084                 addVertexWithColor(result, right, rightColor);
1085             }
1086             else
1087             {
1088                 addVertexWithColor(result, right, rightColor);
1089                 addVertexWithColor(result, left, leftColor);
1090             }
1091         }
1092 
1093         break;
1094     }
1095 
1096     case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
1097     {
1098         vertexCount = 6;
1099 
1100         result.reserve(2 * vertexCount);
1101 
1102         addVertexWithColor(result, tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), leftTopColor);
1103         addVertexWithColor(result, tcu::Vec4(-1.0f, +1.0f, 0.0f, 1.0f), leftBotColor);
1104         addVertexWithColor(result, tcu::Vec4(+1.0f, +1.0f, 0.0f, 1.0f) * slope, rightBotColor);
1105 
1106         addVertexWithColor(result, tcu::Vec4(+1.0f, +1.0f, 0.0f, 1.0f) * slope, rightBotColor);
1107         addVertexWithColor(result, tcu::Vec4(+1.0f, -1.0f, 0.0f, 1.0f) * slope, rightTopColor);
1108         addVertexWithColor(result, tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), leftTopColor);
1109 
1110         break;
1111     }
1112 
1113     case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
1114     {
1115         vertexCount = 4;
1116 
1117         result.reserve(2 * vertexCount);
1118 
1119         addVertexWithColor(result, tcu::Vec4(-1.0f, +1.0f, 0.0f, 1.0f), leftBotColor);
1120         addVertexWithColor(result, tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), leftTopColor);
1121         addVertexWithColor(result, tcu::Vec4(+1.0f, +1.0f, 0.0f, 1.0f) * slope, rightBotColor);
1122         addVertexWithColor(result, tcu::Vec4(+1.0f, -1.0f, 0.0f, 1.0f) * slope, rightTopColor);
1123 
1124         break;
1125     }
1126 
1127     case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
1128     {
1129         vertexCount = 4;
1130 
1131         result.reserve(2 * vertexCount);
1132 
1133         addVertexWithColor(result, tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), leftTopColor);
1134         addVertexWithColor(result, tcu::Vec4(-1.0f, +1.0f, 0.0f, 1.0f), leftBotColor);
1135         addVertexWithColor(result, tcu::Vec4(+1.0f, +1.0f, 0.0f, 1.0f) * slope, rightBotColor);
1136         addVertexWithColor(result, tcu::Vec4(+1.0f, -1.0f, 0.0f, 1.0f) * slope, rightTopColor);
1137 
1138         break;
1139     }
1140 
1141     case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
1142     {
1143         vertexCount = 4 * m_testParams.height;
1144 
1145         result.reserve(2 * vertexCount);
1146 
1147         for (size_t y = 0; y < m_testParams.height; y++)
1148         {
1149             const float ky             = (0.5f + float(y)) / float(m_testParams.height);
1150             const float yy             = -1.0f + 2.0f * ky;
1151             const tcu::Vec4 leftColor  = mix(leftTopColor, leftBotColor, ky);
1152             const tcu::Vec4 rightColor = mix(rightTopColor, rightBotColor, ky);
1153             const tcu::Vec4 preLeft    = tcu::Vec4(-2.0f, yy, 0.0f, 1.0f);
1154             const tcu::Vec4 left       = tcu::Vec4(-1.0f, yy, 0.0f, 1.0f);
1155             const tcu::Vec4 right      = tcu::Vec4(1.0f, yy, 0.0f, 1.0f) * slope;
1156             const tcu::Vec4 afterRight = tcu::Vec4(2.0f, yy, 0.0f, 1.0f) * slope;
1157 
1158             addVertexWithColor(result, preLeft, noneColor);
1159             addVertexWithColor(result, left, leftColor);
1160             addVertexWithColor(result, right, rightColor);
1161             addVertexWithColor(result, afterRight, noneColor);
1162         }
1163 
1164         break;
1165     }
1166 
1167     case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
1168     {
1169         vertexCount = 2 * m_testParams.height + 2;
1170 
1171         result.reserve(2 * vertexCount);
1172 
1173         addVertexWithColor(result, tcu::Vec4(-10.0f, -10.0f, 0.0f, 1.0f), noneColor);
1174 
1175         for (size_t y = 0; y < m_testParams.height; y++)
1176         {
1177             const float ky             = (0.5f + float(y)) / float(m_testParams.height);
1178             const float yy             = -1.0f + 2.0f * ky;
1179             const tcu::Vec4 leftColor  = mix(leftTopColor, leftBotColor, ky);
1180             const tcu::Vec4 rightColor = mix(rightTopColor, rightBotColor, ky);
1181             const tcu::Vec4 left       = tcu::Vec4(-2.0f, yy, 0.0f, 1.0f);
1182             const tcu::Vec4 right      = tcu::Vec4(2.0f, yy, 0.0f, 1.0f) * slope;
1183 
1184             if (y % 2 == 0)
1185             {
1186                 addVertexWithColor(result, left, leftColor);
1187                 addVertexWithColor(result, right, rightColor);
1188             }
1189             else
1190             {
1191                 addVertexWithColor(result, right, rightColor);
1192                 addVertexWithColor(result, left, leftColor);
1193             }
1194         }
1195 
1196         addVertexWithColor(result, tcu::Vec4(+10.0f, +10.0f, 0.0f, 1.0f), noneColor);
1197 
1198         break;
1199     }
1200 
1201     case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
1202     {
1203         vertexCount = 12;
1204 
1205         result.reserve(2 * vertexCount);
1206 
1207         addVertexWithColor(result, tcu::Vec4(-1.0f, +1.0f, 0.0f, 1.0f), leftBotColor);
1208         addVertexWithColor(result, tcu::Vec4(-3.0f, +1.0f, 0.0f, 1.0f), noneColor);
1209         addVertexWithColor(result, tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), leftTopColor);
1210         addVertexWithColor(result, tcu::Vec4(+1.0f, -1.0f, 0.0f, 1.0f) * slope, noneColor);
1211         addVertexWithColor(result, tcu::Vec4(+1.0f, +1.0f, 0.0f, 1.0f) * slope, rightBotColor);
1212         addVertexWithColor(result, tcu::Vec4(+1.0f, +3.0f, 0.0f, 1.0f) * slope, noneColor);
1213 
1214         addVertexWithColor(result, tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), leftTopColor);
1215         addVertexWithColor(result, tcu::Vec4(-1.0f, +1.0f, 0.0f, 1.0f), noneColor);
1216         addVertexWithColor(result, tcu::Vec4(+1.0f, +1.0f, 0.0f, 1.0f) * slope, rightBotColor);
1217         addVertexWithColor(result, tcu::Vec4(+3.0f, +1.0f, 0.0f, 1.0f) * slope, noneColor);
1218         addVertexWithColor(result, tcu::Vec4(+1.0f, -1.0f, 0.0f, 1.0f) * slope, rightTopColor);
1219         addVertexWithColor(result, tcu::Vec4(-1.0f, -3.0f, 0.0f, 1.0f), leftTopColor);
1220 
1221         break;
1222     }
1223 
1224     case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
1225     {
1226         vertexCount = 8;
1227 
1228         result.reserve(2 * vertexCount);
1229 
1230         addVertexWithColor(result, tcu::Vec4(-1.0f, +1.0f, 0.0f, 1.0f), leftBotColor);
1231         addVertexWithColor(result, tcu::Vec4(-3.0f, -1.0f, 0.0f, 1.0f), noneColor);
1232         addVertexWithColor(result, tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), leftTopColor);
1233         addVertexWithColor(result, tcu::Vec4(+1.0f, +3.0f, 0.0f, 1.0f) * slope, noneColor);
1234         addVertexWithColor(result, tcu::Vec4(+1.0f, +1.0f, 0.0f, 1.0f) * slope, rightBotColor);
1235         addVertexWithColor(result, tcu::Vec4(-1.0f, -3.0f, 0.0f, 1.0f), noneColor);
1236         addVertexWithColor(result, tcu::Vec4(+1.0f, -1.0f, 0.0f, 1.0f) * slope, rightTopColor);
1237         addVertexWithColor(result, tcu::Vec4(+1.0f, +3.0f, 0.0f, 1.0f) * slope, noneColor);
1238 
1239         break;
1240     }
1241 
1242     default:
1243         TCU_THROW(InternalError, "Unknown topology");
1244     }
1245 
1246     DE_ASSERT(result.size() == 2 * vertexCount);
1247 
1248     return result;
1249 }
1250 
verify(VkFormat format,BufferWithMemory * referenceBuffer,BufferWithMemory * resultBuffer)1251 bool FragmentShadingBarycentricWeightTestInstance::verify(VkFormat format, BufferWithMemory *referenceBuffer,
1252                                                           BufferWithMemory *resultBuffer)
1253 {
1254     const uint32_t *refernceData = (uint32_t *)referenceBuffer->getAllocation().getHostPtr();
1255     const uint32_t *resultData   = (uint32_t *)resultBuffer->getAllocation().getHostPtr();
1256     tcu::TestLog &log            = m_context.getTestContext().getLog();
1257     const tcu::ConstPixelBufferAccess refImage(mapVkFormat(format), (int)m_testParams.width, (int)m_testParams.height,
1258                                                1u, refernceData);
1259     const tcu::ConstPixelBufferAccess resultImage(mapVkFormat(format), (int)m_testParams.width,
1260                                                   (int)m_testParams.height, 1u, resultData);
1261     const tcu::UVec4 threshold(1, 1, 1, 1);
1262     bool result = tcu::intThresholdCompare(log, "ComparisonResult", "Image comparison result", refImage, resultImage,
1263                                            threshold, tcu::COMPARE_LOG_ON_ERROR);
1264 
1265     return result;
1266 }
1267 
createVertexBuffer(const vector<tcu::Vec4> & vertices)1268 MovePtr<BufferWithMemory> FragmentShadingBarycentricWeightTestInstance::createVertexBuffer(
1269     const vector<tcu::Vec4> &vertices)
1270 {
1271     const DeviceInterface &vkd          = m_context.getDeviceInterface();
1272     const VkDevice device               = m_context.getDevice();
1273     Allocator &allocator                = m_context.getDefaultAllocator();
1274     const VkDeviceSize vertexBufferSize = vertices.size() * sizeof(vertices[0]);
1275     const VkBufferCreateInfo vertexBufferCreateInfo =
1276         makeBufferCreateInfo(vertexBufferSize, m_testParams.useMeshShader ? VK_BUFFER_USAGE_STORAGE_BUFFER_BIT :
1277                                                                             VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
1278     MovePtr<BufferWithMemory> vertexBuffer = MovePtr<BufferWithMemory>(
1279         new BufferWithMemory(vkd, device, allocator, vertexBufferCreateInfo, MemoryRequirement::HostVisible));
1280     Allocation &vertexBufferAlloc = vertexBuffer->getAllocation();
1281 
1282     // Initialize vertex data
1283     deMemcpy(vertexBufferAlloc.getHostPtr(), vertices.data(), (size_t)vertexBufferSize);
1284     flushAlloc(vkd, device, vertexBufferAlloc);
1285 
1286     return vertexBuffer;
1287 }
1288 
iterate(void)1289 tcu::TestStatus FragmentShadingBarycentricWeightTestInstance::iterate(void)
1290 {
1291     const InstanceInterface &vki          = m_context.getInstanceInterface();
1292     const DeviceInterface &vkd            = m_context.getDeviceInterface();
1293     const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
1294     const VkDevice device                 = m_context.getDevice();
1295     const auto &deviceExtensions          = m_context.getDeviceExtensions();
1296     const VkQueue queue                   = m_context.getUniversalQueue();
1297     Allocator &allocator                  = m_context.getDefaultAllocator();
1298     const uint32_t queueFamilyIndex       = m_context.getUniversalQueueFamilyIndex();
1299 
1300     const VkDeviceSize offsetZero   = 0ull;
1301     const VkFormat format           = VK_FORMAT_R8G8B8A8_UNORM;
1302     const uint32_t pixelSize        = mapVkFormat(format).getPixelSize();
1303     const uint32_t width            = static_cast<uint32_t>(m_testParams.width);
1304     const uint32_t height           = static_cast<uint32_t>(m_testParams.height);
1305     const bool dynamicStateTopology = m_testParams.dynamicTopologyInPipeline;
1306     const VkPrimitiveTopology pipelineTopology =
1307         dynamicStateTopology ? primitiveTopologyCastToList(m_testParams.topology) : m_testParams.topology;
1308     const bool withColor           = true;
1309     const bool provokingVertexLast = m_testParams.provokingVertexLast;
1310     const bool useMultisampling    = m_testParams.sampleCount > VK_SAMPLE_COUNT_1_BIT;
1311     const float teta               = deFloatRadians(-float(m_testParams.rotation));
1312     const float mvp[4 * 4]         = {cos(teta), -sin(teta), 0.0f, 0.0f, sin(teta), cos(teta), 0.0f, 0.0f,
1313                                       0.0f,      0.0f,       1.0f, 0.0f, 0.0f,      0.0f,      0.0f, 1.0f};
1314     bool useMeshShader             = m_testParams.useMeshShader;
1315 
1316     const vector<tcu::Vec4> vertices       = generateVertexBuffer();
1317     const uint32_t vertexCount             = static_cast<uint32_t>(vertices.size() / 2);
1318     MovePtr<BufferWithMemory> vertexBuffer = createVertexBuffer(vertices);
1319 
1320     const VkBufferCreateInfo bufferCreateInfo =
1321         makeBufferCreateInfo(width * height * pixelSize,
1322                              useMeshShader ? VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT :
1323                                              VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1324     MovePtr<BufferWithMemory> resultBuffer = MovePtr<BufferWithMemory>(
1325         new BufferWithMemory(vkd, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible));
1326     MovePtr<BufferWithMemory> referenceBuffer = MovePtr<BufferWithMemory>(
1327         new BufferWithMemory(vkd, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible));
1328     const Move<VkRenderPass> renderPass   = makeRenderPass(vkd, device, format, m_testParams.sampleCount);
1329     const Move<VkCommandPool> commandPool = createCommandPool(vkd, device, 0, queueFamilyIndex);
1330     const ShaderWrapper shaderModule =
1331         ShaderWrapper(vkd, device, m_context.getBinaryCollection().get(useMeshShader ? "mesh" : "vert"), 0u);
1332 
1333     const VkImageCreateInfo imageCreateInfo = makeImageCreateInfo(format, width, height, VK_SAMPLE_COUNT_1_BIT);
1334     const VkImageSubresourceRange imageSubresourceRange =
1335         makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
1336     const VkImageCreateInfo msImageCreateInfo = makeImageCreateInfo(format, width, height, m_testParams.sampleCount);
1337     const std::vector<VkClearValue> clearValues(2u, makeClearValueColorU32(0u, 0u, 0u, 0u));
1338 
1339     Move<VkDescriptorSetLayout> descriptorSetLayout;
1340     Move<VkDescriptorPool> descriptorPool;
1341     Move<VkDescriptorSet> descriptorSet;
1342 
1343     if (useMeshShader)
1344     {
1345         DescriptorSetLayoutBuilder layoutBuilder;
1346         layoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_MESH_BIT_EXT);
1347         descriptorSetLayout = layoutBuilder.build(vkd, device);
1348 
1349         DescriptorPoolBuilder poolBuilder;
1350         poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
1351         descriptorPool = poolBuilder.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1352 
1353         descriptorSet = makeDescriptorSet(vkd, device, descriptorPool.get(), *descriptorSetLayout);
1354 
1355         DescriptorSetUpdateBuilder updateBuilder;
1356 
1357         const auto vertexBufferSize     = static_cast<VkDeviceSize>(de::dataSize(vertices));
1358         const auto vertexBufferDescInfo = makeDescriptorBufferInfo(vertexBuffer->get(), 0ull, vertexBufferSize);
1359         updateBuilder.writeSingle(descriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(0u),
1360                                   VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &vertexBufferDescInfo);
1361         updateBuilder.update(vkd, device);
1362     }
1363 
1364     std::vector<VkImageMemoryBarrier> initialImageBarriers(
1365         2, makeImageMemoryBarrier(
1366                VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
1367                VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, VK_NULL_HANDLE, imageSubresourceRange));
1368 
1369     for (size_t ndx = 0; ndx < 2; ndx++)
1370     {
1371         const MovePtr<ImageWithMemory> image = MovePtr<ImageWithMemory>(
1372             new ImageWithMemory(vkd, device, allocator, imageCreateInfo, MemoryRequirement::Any));
1373         const Move<VkImageView> imageView =
1374             makeImageView(vkd, device, **image, VK_IMAGE_VIEW_TYPE_2D, format, imageSubresourceRange);
1375         MovePtr<ImageWithMemory> msImage;
1376         Move<VkImageView> msImageView;
1377 
1378         initialImageBarriers[0].image = **image;
1379 
1380         if (useMultisampling)
1381         {
1382             msImage = MovePtr<ImageWithMemory>(
1383                 new ImageWithMemory(vkd, device, allocator, msImageCreateInfo, MemoryRequirement::Any));
1384             msImageView = makeImageView(vkd, device, **msImage, VK_IMAGE_VIEW_TYPE_2D, format, imageSubresourceRange);
1385             initialImageBarriers[1].image = **msImage;
1386         }
1387 
1388         const std::vector<VkImageView> imageViewVect = {*imageView, *msImageView};
1389         const Move<VkFramebuffer> framebuffer =
1390             makeFramebuffer(vkd, device, *renderPass, 1u + useMultisampling, imageViewVect.data(), width, height);
1391         const Move<VkCommandBuffer> commandBuffer =
1392             allocateCommandBuffer(vkd, device, *commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1393         const BufferWithMemory *buffer = (ndx == 0) ? resultBuffer.get() : referenceBuffer.get();
1394         const string fragModuleName    = (ndx == 0) ? "frag_test" : "frag_reference";
1395         const ShaderWrapper fragModule =
1396             ShaderWrapper(vkd, device, m_context.getBinaryCollection().get(fragModuleName), 0u);
1397         const VkPushConstantRange pushConstantRange = makePushConstantRange(
1398             useMeshShader ? VK_SHADER_STAGE_MESH_BIT_EXT : VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(mvp));
1399         const PipelineLayoutWrapper pipelineLayout(
1400             m_testParams.pipelineConstructionType, vkd, device, useMeshShader ? 1 : 0,
1401             useMeshShader ? &*descriptorSetLayout : nullptr, 1, &pushConstantRange);
1402         const auto pipelineWrapper = makeGraphicsPipeline(
1403             useMeshShader, m_testParams.pipelineConstructionType, vki, vkd, physicalDevice, device, deviceExtensions,
1404             pipelineLayout, *renderPass, shaderModule, fragModule, width, height, pipelineTopology,
1405             m_testParams.sampleCount, withColor, provokingVertexLast, dynamicStateTopology);
1406         const VkPipeline pipeline = pipelineWrapper->getPipeline();
1407 
1408         beginCommandBuffer(vkd, *commandBuffer);
1409         {
1410             cmdPipelineImageMemoryBarrier(vkd, *commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
1411                                           VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, initialImageBarriers.data(),
1412                                           1u + useMultisampling);
1413 
1414             if (dynamicStateTopology)
1415                 vkd.cmdSetPrimitiveTopology(*commandBuffer, m_testParams.topology);
1416 
1417             beginRenderPass(vkd, *commandBuffer, *renderPass, *framebuffer, makeRect2D(width, height),
1418                             1u + useMultisampling, clearValues.data());
1419             {
1420                 vkd.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
1421 
1422                 if (useMeshShader)
1423                     vkd.cmdBindDescriptorSets(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0u,
1424                                               1u, &descriptorSet.get(), 0u, nullptr);
1425                 else
1426                     vkd.cmdBindVertexBuffers(*commandBuffer, 0u, 1u, &vertexBuffer->get(), &offsetZero);
1427 
1428                 vkd.cmdPushConstants(*commandBuffer, *pipelineLayout,
1429                                      useMeshShader ? VK_SHADER_STAGE_MESH_BIT_EXT : VK_SHADER_STAGE_VERTEX_BIT, 0u,
1430                                      sizeof(mvp), &mvp);
1431 
1432                 if (useMeshShader)
1433                 {
1434                     const tcu::IVec3 groupCount = (m_testParams.topology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST) ?
1435                                                       tcu::IVec3(256u, 8u, 8u) :
1436                                                       tcu::IVec3(1u, 1u, 1u);
1437                     vkd.cmdDrawMeshTasksEXT(*commandBuffer, groupCount.x(), groupCount.y(), groupCount.z());
1438                 }
1439                 else
1440                     vkd.cmdDraw(*commandBuffer, vertexCount, 1u, 0u, 0u);
1441             }
1442             endRenderPass(vkd, *commandBuffer);
1443 
1444             copyImageToBuffer(vkd, *commandBuffer, image->get(), buffer->get(), tcu::IVec2(width, height));
1445         }
1446         endCommandBuffer(vkd, *commandBuffer);
1447         submitCommandsAndWait(vkd, device, queue, *commandBuffer);
1448 
1449         invalidateMappedMemoryRange(vkd, device, buffer->getAllocation().getMemory(),
1450                                     buffer->getAllocation().getOffset(), VK_WHOLE_SIZE);
1451     }
1452 
1453     if (verify(format, referenceBuffer.get(), resultBuffer.get()))
1454         return tcu::TestStatus::pass("Pass");
1455     else
1456         return tcu::TestStatus::fail("Fail");
1457 }
1458 
1459 class FragmentShadingBarycentricTestCase : public TestCase
1460 {
1461 public:
1462     FragmentShadingBarycentricTestCase(tcu::TestContext &context, const char *name, const TestParams testParams);
1463     ~FragmentShadingBarycentricTestCase(void);
1464 
1465     virtual void checkSupport(Context &context) const;
1466     virtual void initPrograms(SourceCollections &programCollection) const;
1467     virtual TestInstance *createInstance(Context &context) const;
1468 
1469 private:
1470     void initDataPrograms(SourceCollections &programCollection) const;
1471     void initMiscDataPrograms(SourceCollections &programCollection) const;
1472     void initMiscDataTessPrograms(SourceCollections &programCollection, map<string, string> &attributes) const;
1473     void initMiscDataGeomPrograms(SourceCollections &programCollection, map<string, string> &attributes) const;
1474     void initWeightPrograms(SourceCollections &programCollection) const;
1475     string generateDataMeshShader(void) const;
1476     string generateWeightMeshShader(void) const;
1477     string getDataPrimitiveFormula(void) const;
1478     string getDataVertexFormula(const uint32_t vertex, const bool *provokingVertexLastPtr = nullptr) const;
1479     string getDataProvokingVertexFormula(const bool *provokingVertexLastPtr = nullptr) const;
1480     TestParams m_testParams;
1481 };
1482 
FragmentShadingBarycentricTestCase(tcu::TestContext & context,const char * name,const TestParams testParams)1483 FragmentShadingBarycentricTestCase::FragmentShadingBarycentricTestCase(tcu::TestContext &context, const char *name,
1484                                                                        const TestParams testParams)
1485     : vkt::TestCase(context, name)
1486     , m_testParams(testParams)
1487 {
1488 }
1489 
~FragmentShadingBarycentricTestCase(void)1490 FragmentShadingBarycentricTestCase::~FragmentShadingBarycentricTestCase(void)
1491 {
1492 }
1493 
checkSupport(Context & context) const1494 void FragmentShadingBarycentricTestCase::checkSupport(Context &context) const
1495 {
1496     const auto &vki           = context.getInstanceInterface();
1497     const auto physicalDevice = context.getPhysicalDevice();
1498 
1499     context.requireDeviceFunctionality("VK_KHR_fragment_shader_barycentric");
1500 
1501     const VkPhysicalDeviceFragmentShaderBarycentricFeaturesKHR &fragmentShaderBarycentricFeatures =
1502         context.getFragmentShaderBarycentricFeatures();
1503 
1504     if (!fragmentShaderBarycentricFeatures.fragmentShaderBarycentric)
1505         TCU_THROW(NotSupportedError,
1506                   "Requires VkPhysicalDeviceFragmentShaderBarycentricFeaturesKHR.fragmentShaderBarycentric");
1507 
1508     checkPipelineConstructionRequirements(vki, physicalDevice, m_testParams.pipelineConstructionType);
1509 
1510     if (m_testParams.provokingVertexLast)
1511     {
1512         context.requireDeviceFunctionality("VK_EXT_provoking_vertex");
1513 
1514         const VkPhysicalDeviceProvokingVertexFeaturesEXT &provokingVertexFeaturesEXT =
1515             context.getProvokingVertexFeaturesEXT();
1516 
1517         if (!provokingVertexFeaturesEXT.provokingVertexLast)
1518             TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceProvokingVertexFeaturesEXT.provokingVertexLast");
1519     }
1520 
1521     if (m_testParams.dynamicTopologyInPipeline)
1522     {
1523         context.requireDeviceFunctionality("VK_EXT_extended_dynamic_state");
1524 
1525         const VkPhysicalDeviceExtendedDynamicStateFeaturesEXT &extendedDynamicStateFeaturesEXT =
1526             context.getExtendedDynamicStateFeaturesEXT();
1527 
1528         if (!extendedDynamicStateFeaturesEXT.extendedDynamicState)
1529             TCU_THROW(NotSupportedError,
1530                       "Requires VkPhysicalDeviceExtendedDynamicStateFeaturesEXT.extendedDynamicState");
1531     }
1532 
1533     if (m_testParams.useMeshShader)
1534     {
1535         context.requireDeviceFunctionality("VK_EXT_mesh_shader");
1536 
1537         const VkPhysicalDeviceMeshShaderFeaturesEXT &meshShaderFeaturesEXT = context.getMeshShaderFeaturesEXT();
1538 
1539         if (!meshShaderFeaturesEXT.meshShader)
1540             TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceMeshShaderFeaturesEXT.meshShader");
1541     }
1542 
1543     if ((m_testParams.dataType == glu::TYPE_DOUBLE) || (m_testParams.dataType == glu::TYPE_DOUBLE_VEC2) ||
1544         (m_testParams.dataType == glu::TYPE_DOUBLE_VEC3) || (m_testParams.dataType == glu::TYPE_DOUBLE_VEC4))
1545     {
1546         VkPhysicalDeviceFeatures2 features2;
1547         deMemset(&features2, 0, sizeof(features2));
1548         features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
1549         features2.pNext = nullptr;
1550         vki.getPhysicalDeviceFeatures2(physicalDevice, &features2);
1551         if (features2.features.shaderFloat64 != VK_TRUE)
1552         {
1553             TCU_THROW(NotSupportedError, "shaderFloat64 not supported");
1554         }
1555     }
1556 
1557     if ((m_testParams.testSubtype == TEST_SUBTYPE_TESS_SHADER) ||
1558         (m_testParams.testSubtype == TEST_SUBTYPE_TESSGEOM_SHADER))
1559         context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_TESSELLATION_SHADER);
1560 
1561     if ((m_testParams.testSubtype == TEST_SUBTYPE_GEOMETRY_SHADER) ||
1562         (m_testParams.testSubtype == TEST_SUBTYPE_TESSGEOM_SHADER))
1563         context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
1564 
1565     if ((m_testParams.testSubtype == TEST_SUBTYPE_MSAA_INTERPOLATE_AT_SAMPLE) ||
1566         (m_testParams.testSubtype == TEST_SUBTYPE_MSAA_INTERPOLATE_AT_OFFSET))
1567         context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SAMPLE_RATE_SHADING);
1568 }
1569 
createInstance(Context & context) const1570 TestInstance *FragmentShadingBarycentricTestCase::createInstance(Context &context) const
1571 {
1572     switch (m_testParams.testType)
1573     {
1574     case TEST_TYPE_DATA:
1575         return new FragmentShadingBarycentricDataTestInstance(context, m_testParams);
1576     case TEST_TYPE_WEIGHTS:
1577         return new FragmentShadingBarycentricWeightTestInstance(context, m_testParams);
1578     default:
1579         TCU_THROW(InternalError, "Unknown testType");
1580     }
1581 }
1582 
initPrograms(SourceCollections & programCollection) const1583 void FragmentShadingBarycentricTestCase::initPrograms(SourceCollections &programCollection) const
1584 {
1585     switch (m_testParams.testType)
1586     {
1587     case TEST_TYPE_DATA:
1588         if (m_testParams.testSubtype == TEST_SUBTYPE_PERVERTEX_CORRECTNESS)
1589             initMiscDataPrograms(programCollection);
1590         else
1591             initDataPrograms(programCollection);
1592         break;
1593     case TEST_TYPE_WEIGHTS:
1594         initWeightPrograms(programCollection);
1595         break;
1596     default:
1597         TCU_THROW(InternalError, "Unknown testType");
1598     }
1599 }
1600 
getDataPrimitiveFormula(void) const1601 string FragmentShadingBarycentricTestCase::getDataPrimitiveFormula(void) const
1602 {
1603     if (m_testParams.clipVertices)
1604     {
1605         DE_ASSERT(m_testParams.topology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST);
1606         return "((x - 2) * 2 < y) ? 0 : 1";
1607     }
1608     const char *primitiveFormulas[] = {
1609         "w * y + x",       //  VK_PRIMITIVE_TOPOLOGY_POINT_LIST
1610         "y",               //  VK_PRIMITIVE_TOPOLOGY_LINE_LIST
1611         "2*y",             //  VK_PRIMITIVE_TOPOLOGY_LINE_STRIP
1612         "(x < y) ? 0 : 1", //  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST
1613         "(x < y) ? 0 : 1", //  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP
1614         "(x < y) ? 0 : 1", //  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN
1615         "y",               //  VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY
1616         "2*y",             //  VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY
1617         "(x < y) ? 0 : 1", //  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY
1618         "(x < y) ? 0 : 1", //  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY
1619         "(x < y) ? 0 : 1", //  VK_PRIMITIVE_TOPOLOGY_PATCH_LIST
1620     };
1621 
1622     DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(primitiveFormulas) == vk::VK_PRIMITIVE_TOPOLOGY_LAST);
1623     DE_ASSERT(m_testParams.topology < DE_LENGTH_OF_ARRAY(primitiveFormulas));
1624 
1625     return primitiveFormulas[m_testParams.topology];
1626 }
1627 
getDataVertexFormula(const uint32_t vertex,const bool * provokingVertexLastPtr) const1628 string FragmentShadingBarycentricTestCase::getDataVertexFormula(const uint32_t vertex,
1629                                                                 const bool *provokingVertexLastPtr) const
1630 {
1631     typedef const char *TriVertexFormula[3];
1632 
1633     // Accoriding "Barycentric Interpolation" section
1634     const TriVertexFormula topologyVertexFormulas[] = {
1635         {"p", "p", "p"},                                 //  VK_PRIMITIVE_TOPOLOGY_POINT_LIST
1636         {"2*p", "2*p+1", "2*p+1"},                       //  VK_PRIMITIVE_TOPOLOGY_LINE_LIST
1637         {"p", "p+1", "p+1"},                             //  VK_PRIMITIVE_TOPOLOGY_LINE_STRIP
1638         {"3*p", "3*p+1", "3*p+2"},                       //  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST
1639         {"p", "even?p+1:p+2", "even?p+2:p+1"},           //  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP
1640         {"p+1", "p+2", "0"},                             //  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN
1641         {"4*p+1", "4*p+2", "4*p+2"},                     //  VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY
1642         {"p+1", "p+2", "p+2"},                           //  VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY
1643         {"6*p", "6*p+2", "6*p+4"},                       //  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY
1644         {"2*p", "even?2*p+2:2*p+4", "even?2*p+4:2*p+2"}, //  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY
1645         {"3*p", "3*p+1", "3*p+2"},                       //  VK_PRIMITIVE_TOPOLOGY_PATCH_LIST
1646     };
1647     const TriVertexFormula topologyVertexFormulasLast[] = {
1648         {"even?p:p+1", "even?p+1:p", "p+2"},           //  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP
1649         {"0", "p+1", "p+2"},                           //  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN
1650         {"even?2*p:2*p+2", "even?2*p+2:2*p", "2*p+4"}, //  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY
1651     };
1652     const bool provokingVertexLast =
1653         provokingVertexLastPtr ? (*provokingVertexLastPtr) : m_testParams.provokingVertexLast;
1654     const bool provokingLastTriangleStrip =
1655         provokingVertexLast && m_testParams.topology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
1656     const bool provokingLastTriangleFan =
1657         provokingVertexLast && m_testParams.topology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN;
1658     const bool provokingLastTriangleStripAdj =
1659         provokingVertexLast && m_testParams.topology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY;
1660     const TriVertexFormula *triVertexFormula =
1661         provokingLastTriangleStrip    ? &topologyVertexFormulasLast[0] :
1662         provokingLastTriangleFan      ? &topologyVertexFormulasLast[1] :
1663         provokingLastTriangleStripAdj ? &topologyVertexFormulasLast[2] :
1664                                         &topologyVertexFormulas[static_cast<size_t>(m_testParams.topology)];
1665 
1666     DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(topologyVertexFormulas) == vk::VK_PRIMITIVE_TOPOLOGY_LAST);
1667     DE_ASSERT(vertex < DE_LENGTH_OF_ARRAY(triVertexFormula[0]));
1668 
1669     return "(" + string(triVertexFormula[0][vertex]) + ")";
1670 }
1671 
getDataProvokingVertexFormula(const bool * provokingVertexLastPtr) const1672 string FragmentShadingBarycentricTestCase::getDataProvokingVertexFormula(const bool *provokingVertexLastPtr) const
1673 {
1674     typedef const char *ProvokingVertexFormula[2];
1675 
1676     const ProvokingVertexFormula provokingVertexFormulas[] = {
1677         {"p", "p"},       //  VK_PRIMITIVE_TOPOLOGY_POINT_LIST
1678         {"2*p", "2*p+1"}, //  VK_PRIMITIVE_TOPOLOGY_LINE_LIST
1679         {"p", "p+1"},     //  VK_PRIMITIVE_TOPOLOGY_LINE_STRIP
1680         {"3*p", "3*p+2"}, //  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST
1681         {"p", "p+2"},     //  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP
1682         {
1683             "p+1",
1684             "p+2",
1685         },                  //  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN
1686         {"4*p+1", "4*p+2"}, //  VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY
1687         {"p+1", "p+2"},     //  VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY
1688         {"6*p", "6*p+4"},   //  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY
1689         {"2*p", "2*p+4"},   //  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY
1690         {
1691             "",
1692             "",
1693         }, //  VK_PRIMITIVE_TOPOLOGY_PATCH_LIST
1694     };
1695 
1696     const bool provokingVertexLast =
1697         provokingVertexLastPtr ? (*provokingVertexLastPtr) : m_testParams.provokingVertexLast;
1698     const ProvokingVertexFormula &provokingVertexFormula =
1699         provokingVertexFormulas[static_cast<size_t>(m_testParams.topology)];
1700 
1701     return "(" + string(provokingVertexFormula[provokingVertexLast ? 1 : 0]) + ")";
1702 }
1703 
generateDataMeshShader() const1704 string FragmentShadingBarycentricTestCase::generateDataMeshShader() const
1705 {
1706 
1707     string meshShader;
1708 
1709     switch (m_testParams.topology)
1710     {
1711     case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
1712     {
1713         meshShader = "#version 450\n"
1714                      "#extension GL_EXT_mesh_shader : enable\n"
1715                      "\n"
1716                      "${dataStruct}\n"
1717                      "layout(local_size_x = 8, local_size_y = 4, local_size_z = 1) in;\n"
1718                      "layout(triangles) out;\n"
1719                      "layout(max_vertices=6, max_primitives=6) out;\n"
1720                      "\n"
1721                      "layout(set = 0, binding = 0) buffer PerVertexData{ \n"
1722                      "    vec4 vertexBuffer[6];\n"
1723                      "} pvd;\n"
1724                      "layout (location=0) out ${typePrefix} data[]${typeSuffix};\n" +
1725                      string(m_testParams.testWithInterpolation ?
1726                                 "layout(location = ${locInterp}) out ${typePrefix} dataInterp[]${typeSuffix};\n" :
1727                                 "") +
1728                      string(m_testParams.testWithFlatInterpolation ?
1729                                 "layout(location = ${locFlat}) out ${typePrefix} dataFlat[]${typeSuffix};\n" :
1730                                 "") +
1731                      "\n"
1732                      "out gl_MeshPerVertexEXT \n"
1733                      "{\n"
1734                      "    vec4  gl_Position;\n"
1735                      "    float gl_PointSize;\n"
1736                      "} gl_MeshVerticesEXT[];\n"
1737                      "\n"
1738                      "void main()\n"
1739                      "{\n"
1740                      "    uint maxVertex = 6;\n"
1741                      "    uint maxPrimitive = 2;\n"
1742                      "    SetMeshOutputsEXT(maxVertex, maxPrimitive);\n"
1743                      "    const uint vertex = gl_LocalInvocationIndex;\n"
1744                      "    const uint primitive = gl_LocalInvocationIndex;\n"
1745                      "    const uvec3 indices[2] = uvec3[](\n"
1746                      "        uvec3(0, 1, 2),\n"
1747                      "        uvec3(3, 4, 5)\n"
1748                      "    );\n"
1749                      "    if (vertex < maxVertex)\n"
1750                      "    {\n"
1751                      "        gl_MeshVerticesEXT[vertex].gl_Position = pvd.vertexBuffer[vertex];\n"
1752                      "        gl_MeshVerticesEXT[vertex].gl_PointSize = 1.0;\n"
1753                      "        uint n  = vertex + 1;\n"
1754                      "        data[vertex] = ${value};\n" +
1755                      string(m_testParams.testWithInterpolation ? "    dataInterp[vertex]    = ${value};\n" : "") +
1756                      string(m_testParams.testWithFlatInterpolation ? "    dataFlat[vertex]      = ${value};\n" : "") +
1757                      "    }\n"
1758                      "    if(primitive < maxPrimitive){\n"
1759                      "        gl_PrimitiveTriangleIndicesEXT[primitive] = indices[primitive];\n"
1760                      "    }\n"
1761                      "}\n";
1762 
1763         return meshShader;
1764     }
1765     case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
1766     {
1767         meshShader = "#version 450\n"
1768                      "#extension GL_EXT_mesh_shader : enable\n"
1769                      "\n"
1770                      "${dataStruct}\n"
1771                      "layout(local_size_x = 8, local_size_y = 4, local_size_z = 1) in;\n"
1772                      "layout(lines) out;\n"
1773                      "layout(max_vertices=16, max_primitives=16) out;\n"
1774                      "\n"
1775                      "layout(set = 0, binding = 0) buffer PerVertexData{ \n"
1776                      "    vec4 vertexBuffer[16];\n"
1777                      "} pvd;\n"
1778                      "layout (location=0) out ${typePrefix} data[]${typeSuffix};\n" +
1779                      string(m_testParams.testWithInterpolation ?
1780                                 "layout(location = ${locInterp}) out ${typePrefix} dataInterp[]${typeSuffix};\n" :
1781                                 "") +
1782                      string(m_testParams.testWithFlatInterpolation ?
1783                                 "layout(location = ${locFlat}) out ${typePrefix} dataFlat[]${typeSuffix};\n" :
1784                                 "") +
1785                      "\n"
1786                      "out gl_MeshPerVertexEXT \n"
1787                      "{\n"
1788                      "    vec4  gl_Position;\n"
1789                      "    float gl_PointSize;\n"
1790                      "} gl_MeshVerticesEXT[];\n"
1791                      "\n"
1792                      "void main()\n"
1793                      "{\n"
1794                      "    uint maxVertex = 16;\n"
1795                      "    uint maxPrimitive = 8;\n"
1796                      "    SetMeshOutputsEXT(maxVertex, maxPrimitive);\n"
1797                      "    const uint vertex = gl_LocalInvocationIndex;\n"
1798                      "    const uint primitive = gl_LocalInvocationIndex;\n"
1799                      "    if (vertex < maxVertex)\n"
1800                      "    {\n"
1801                      "        gl_MeshVerticesEXT[vertex].gl_Position = pvd.vertexBuffer[vertex];\n"
1802                      "        gl_MeshVerticesEXT[vertex].gl_PointSize = 1.0;\n"
1803                      "        uint n  = vertex + 1;\n"
1804                      "        data[vertex] = ${value};\n" +
1805                      string(m_testParams.testWithInterpolation ? "    dataInterp[vertex]    = ${value};\n" : "") +
1806                      string(m_testParams.testWithFlatInterpolation ? "    dataFlat[vertex]      = ${value};\n" : "") +
1807                      "    }\n"
1808                      "    if(primitive < maxPrimitive){\n"
1809                      "        gl_PrimitiveLineIndicesEXT[vertex] = uvec2(vertex * 2, vertex * 2 + 1u);\n"
1810                      "    }\n"
1811                      "}\n";
1812 
1813         return meshShader;
1814     }
1815     case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
1816     {
1817         meshShader = "#version 450\n"
1818                      "#extension GL_EXT_mesh_shader : enable\n"
1819                      "\n"
1820                      "${dataStruct}\n"
1821                      "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
1822                      "layout(points) out;\n"
1823                      "layout(max_vertices=1, max_primitives = 1) out;\n"
1824                      "layout(set = 0, binding = 0) buffer PerVertexData{ \n"
1825                      "    vec4 vertexBuffer[64];\n"
1826                      "} pvd;\n"
1827                      "layout (location=0) out ${typePrefix} data[]${typeSuffix};\n" +
1828                      string(m_testParams.testWithInterpolation ?
1829                                 "layout(location = ${locInterp}) out ${typePrefix} dataInterp[]${typeSuffix};\n" :
1830                                 "") +
1831                      string(m_testParams.testWithFlatInterpolation ?
1832                                 "layout(location = ${locFlat}) out ${typePrefix} dataFlat[]${typeSuffix};\n" :
1833                                 "") +
1834                      "\n"
1835                      "out gl_MeshPerVertexEXT \n"
1836                      "{\n"
1837                      "    vec4  gl_Position;\n"
1838                      "    float gl_PointSize;\n"
1839                      "} gl_MeshVerticesEXT[];\n"
1840                      "\n"
1841                      "void main()\n"
1842                      "{\n"
1843                      "    SetMeshOutputsEXT(1u, 1u);\n"
1844                      "    const uint vertex = gl_LocalInvocationIndex;\n"
1845                      "    const uint workGroupIndex = gl_NumWorkGroups.x * gl_NumWorkGroups.y * gl_WorkGroupID.z + "
1846                      "gl_NumWorkGroups.x * gl_WorkGroupID.y + gl_WorkGroupID.x;\n"
1847                      "    uint jobId = workGroupIndex + gl_LocalInvocationIndex;\n"
1848                      "    gl_MeshVerticesEXT[vertex].gl_Position = pvd.vertexBuffer[jobId];\n"
1849                      "    gl_MeshVerticesEXT[vertex].gl_PointSize = 1.0;\n"
1850                      "    gl_PrimitivePointIndicesEXT[vertex] = vertex;\n"
1851                      "    uint n  = jobId + 1;\n"
1852                      "    data[vertex] = ${value};\n" +
1853                      string(m_testParams.testWithInterpolation ? "    dataInterp[vertex]    = ${value};\n" : "") +
1854                      string(m_testParams.testWithFlatInterpolation ? "    dataFlat[vertex]      = ${value};\n" : "") +
1855                      "}\n";
1856 
1857         return meshShader;
1858     }
1859     default:
1860         TCU_THROW(InternalError, "Unknown topology");
1861     }
1862 }
1863 
initDataPrograms(SourceCollections & programCollection) const1864 void FragmentShadingBarycentricTestCase::initDataPrograms(SourceCollections &programCollection) const
1865 {
1866     map<string, string> attributes;
1867     const string primitiveType  = string(getDataTypeName(m_testParams.dataType));
1868     const string dataStructType = m_testParams.aggregate == 1 ? "struct DataStruct {" + primitiveType + " q;};" : "";
1869     const string typePrefix     = m_testParams.aggregate == 0 ? primitiveType :
1870                                   m_testParams.aggregate == 1 ? "DataStruct" :
1871                                                                 primitiveType;
1872     const string typeSuffix     = m_testParams.aggregate == 0 ? "" :
1873                                   m_testParams.aggregate == 1 ? "" :
1874                                                                 "[" + de::toString(m_testParams.aggregate) + "]";
1875     const int scalarSize        = getDataTypeScalarSize(m_testParams.dataType);
1876     const string scalarName     = getDataTypeName(getDataTypeScalarType(m_testParams.dataType));
1877     const string vectoredInit   = (scalarSize == 1) ? primitiveType + "(n)" :
1878                                   (scalarSize == 2) ? primitiveType + "(" + scalarName + "(n), " + scalarName + "(2*n))" :
1879                                   (scalarSize == 3) ? primitiveType + "(" + scalarName + "(n), " + scalarName +
1880                                                         "(2*n), " + scalarName + "(4*n))" :
1881                                   (scalarSize == 4) ? primitiveType + "(" + scalarName + "(n), " + scalarName +
1882                                                         "(2*n), " + scalarName + "(4*n), " + scalarName + "(8*n))" :
1883                                                       "NOT IMPLEMENTED";
1884     const string value          = m_testParams.aggregate == 0 ? vectoredInit :
1885                                   m_testParams.aggregate == 1 ? "DataStruct(" + vectoredInit + ")" :
1886                                   m_testParams.aggregate == 2 ? primitiveType + "[2](" + vectoredInit + ", " + scalarName +
1887                                                            "(3)*" + vectoredInit + ")" :
1888                                                                 "NOT IMPLEMENTED";
1889     const size_t componentCount = getComponentCount(m_testParams);
1890     const string scalarized     = (scalarSize == 1) ? "e${R}," :
1891                                   (scalarSize == 2) ? "e${R}.x,e${R}.y," :
1892                                   (scalarSize == 3) ? "e${R}.x,e${R}.y,e${R}.z," :
1893                                   (scalarSize == 4) ? "e${R}.x,e${R}.y,e${R}.z,e${R}.w," :
1894                                                       "NOT IMPLEMENTED";
1895     const string deaggregated =
1896         m_testParams.aggregate == 0 ? replace(scalarized, "${R}", "${S}") :
1897         m_testParams.aggregate == 1 ? replace(scalarized, "${R}", "${S}.q") :
1898         m_testParams.aggregate == 2 ? replace(scalarized, "${R}", "${S}[0]") + replace(scalarized, "${R}", "${S}[1]") :
1899                                       "NOT IMPLEMENTED";
1900     const string unwrap =
1901         replace(deaggregated, "${S}", "A") + replace(deaggregated, "${S}", "B") + replace(deaggregated, "${S}", "C");
1902     const string expected = unwrap.substr(0, unwrap.size() - 1);
1903     const string arrived  = replace(expected, "e", "v");
1904 
1905     const string unwrapFlat   = replace(deaggregated, "${S}", "FlatV");
1906     const string expectedFlat = unwrapFlat.substr(0, unwrapFlat.size() - 1);
1907     const string arrivedFlat  = replace(expectedFlat, "e", "v");
1908 
1909     const string unwraIntrp    = replace(deaggregated, "${S}", "IntrpV");
1910     const string expectedIntrp = unwraIntrp.substr(0, unwraIntrp.size() - 1);
1911     const string arrivedIntrp  = replace(expectedIntrp, "e", "v");
1912 
1913     const string dynamicIndexing =
1914         m_testParams.dynamicIndexing ? "layout(push_constant) uniform PushConstant { uint n[3]; } pc;\n" : "";
1915     const string i0              = m_testParams.dynamicIndexing ? "pc.n[0]" : "0";
1916     const string i1              = m_testParams.dynamicIndexing ? "pc.n[1]" : "1";
1917     const string i2              = m_testParams.dynamicIndexing ? "pc.n[2]" : "2";
1918     const string primitiveId     = getDataPrimitiveFormula();
1919     const string vertexFormula[] = {getDataVertexFormula(0), getDataVertexFormula(1), getDataVertexFormula(2)};
1920     string intrpFormula;
1921     for (size_t i = 0; i < std::max(static_cast<size_t>(1), m_testParams.aggregate); ++i)
1922     {
1923         string acc = m_testParams.aggregate > 1 ? "[" + de::toString(i) + "]" : "";
1924         if (m_testParams.aggregate == 1)
1925             acc += ".q";
1926         intrpFormula +=
1927             "eA" + acc + " * gl_BaryCoordEXT.x + eB" + acc + " * gl_BaryCoordEXT.y + eC" + acc + " * gl_BaryCoordEXT.z";
1928         if (i + 1 < m_testParams.aggregate)
1929         {
1930             intrpFormula += ", ";
1931         }
1932     }
1933 
1934     const ShaderBuildOptions buildOptions(programCollection.usedVulkanVersion, SPIRV_VERSION_1_4, 0u);
1935 
1936     const tcu::StringTemplate meshShader(m_testParams.useMeshShader ? generateDataMeshShader() : "");
1937 
1938     const tcu::StringTemplate vertShader(
1939         string("#version 450\n"
1940                "#extension GL_EXT_fragment_shader_barycentric : require\n"
1941                "\n"
1942                "${dataStruct}\n"
1943                "\n"
1944                "layout(location = 0) in  vec4 in_position;\n"
1945                "layout(location = 0) out ${typePrefix} data${typeSuffix};\n" +
1946                string(m_testParams.testWithInterpolation ?
1947                           "layout(location = ${locInterp}) out ${typePrefix} dataInterp${typeSuffix};\n" :
1948                           "") +
1949                string(m_testParams.testWithFlatInterpolation ?
1950                           "layout(location = ${locFlat}) out ${typePrefix} dataFlat${typeSuffix};\n" :
1951                           "") +
1952                "\n"
1953                "out gl_PerVertex\n"
1954                "{\n"
1955                "    vec4  gl_Position;\n"
1956                "    float gl_PointSize;\n"
1957                "};\n"
1958                "\n"
1959                "void main()\n"
1960                "{\n"
1961                "    const int n  = gl_VertexIndex + 1;\n"
1962                "    data         = ${value};\n" +
1963                string(m_testParams.testWithInterpolation ? "    dataInterp    = ${value};\n" : "") +
1964                string(m_testParams.testWithFlatInterpolation ? "    dataFlat      = ${value};\n" : "") +
1965                "    gl_PointSize = 1.0;\n"
1966                "    gl_Position  = in_position;\n"
1967                "}\n"));
1968     const tcu::StringTemplate fragShader(
1969         string("#version 450\n") +
1970         "#extension GL_EXT_fragment_shader_barycentric : require\n"
1971         "\n"
1972         "${dataStruct}\n"
1973         "\n"
1974         "${dynamicIndexing}\n" +
1975         string(m_testParams.testWithInterpolation ?
1976                    "layout(location = ${locInterp}) in ${typePrefix} dataIntrp${typeSuffix};\n" :
1977                    "") +
1978         string(m_testParams.testWithFlatInterpolation ?
1979                    "layout(location = ${locFlat}) flat in ${typePrefix} dataFlat${typeSuffix};\n" :
1980                    "") +
1981         "layout(location = 0) out uvec4 out_color;\n"
1982         "\n" +
1983         string(((m_testParams.testSubtype == TEST_SUBTYPE_TESS_SHADER) ||
1984                 (m_testParams.testSubtype == TEST_SUBTYPE_TESSGEOM_SHADER)) ?
1985                    "struct InDataStruct {uint idx; ${typePrefix} data${typeSuffix};};\n"
1986                    "layout(location = 0) pervertexEXT in InDataStruct inParam[];\n"
1987                    "void getData(uint i, out ${typePrefix} ds${typeSuffix})\n"
1988                    "{\n"
1989                    "    for(uint k = 0; k < 3; k++)\n"
1990                    "    {\n"
1991                    "        if (inParam[k].idx == i)\n"
1992                    "            ds = " +
1993                        string(m_testParams.aggregate == 2 ?
1994                                   "${typePrefix}${typeSuffix}(inParam[k].data[0],inParam[k].data[1])" :
1995                                   "inParam[k].data") +
1996                        ";\n"
1997                        "    }\n"
1998                        "}\n" :
1999                    "layout(location = 0) pervertexEXT in ${typePrefix} data[]${typeSuffix};\n") +
2000         "void main()\n"
2001         "{\n"
2002         "    const int  w    = " +
2003         de::toString(m_testParams.width) +
2004         ";\n"
2005         "    const int  h    = " +
2006         de::toString(m_testParams.height) +
2007         ";\n"
2008         "    const int  x    = int(gl_FragCoord.x - 0.5f);\n"
2009         "    const int  y    = int(gl_FragCoord.y - 0.5f);\n"
2010         "    const int  p    = ${primitiveId};\n"
2011         "    const bool even = (p%2 == 0);\n"
2012         "\n"
2013         "    ${typePrefix} eA${typeSuffix}; { const int n = 1 + ${vertexFormula0}; eA = ${value}; }\n"
2014         "    ${typePrefix} eB${typeSuffix}; { const int n = 1 + ${vertexFormula1}; eB = ${value}; }\n"
2015         "    ${typePrefix} eC${typeSuffix}; { const int n = 1 + ${vertexFormula2}; eC = ${value}; }\n" +
2016         "\n"
2017         "    ${scalarName} e[${componentCount}] = { ${expected} };\n" +
2018         string(
2019             m_testParams.testWithInterpolation ?
2020                 "    ${typePrefix} eIntrpV${typeSuffix}; {eIntrpV = ${typePrefix}${typeSuffix}(${intrpFormula}); }\n" :
2021                 "") +
2022         string(m_testParams.testWithInterpolation ?
2023                    "    ${scalarName} eIntrp[${componentCount} / 3] = { ${expectedIntrp} };\n" :
2024                    "") +
2025         string(m_testParams.testWithFlatInterpolation ? "    ${typePrefix} eFlatV${typeSuffix}; { const int n = 1 + "
2026                                                         "${vertexFormulaFlat}; eFlatV = ${value}; }\n" :
2027                                                         "") +
2028         string(m_testParams.testWithFlatInterpolation ?
2029                    "    ${scalarName} eFlat[${componentCount} / 3] = { ${expectedFlat} };\n" :
2030                    "") +
2031         "\n" +
2032         string(
2033             ((m_testParams.testSubtype == TEST_SUBTYPE_TESS_SHADER) ||
2034              (m_testParams.testSubtype == TEST_SUBTYPE_TESSGEOM_SHADER)) ?
2035                 "    ${typePrefix} vA${typeSuffix}; { getData(${i0}, vA); }\n"
2036                 "    ${typePrefix} vB${typeSuffix}; { getData(${i1}, vB); }\n"
2037                 "    ${typePrefix} vC${typeSuffix}; { getData(${i2}, vC); }\n" :
2038                 "    ${typePrefix} vA${typeSuffix}; { vA = " +
2039                     string(m_testParams.aggregate == 2 ? "${typePrefix}${typeSuffix}(data[${i0}][0],data[${i0}][1])" :
2040                                                          "data[${i0}]") +
2041                     "; }\n"
2042                     "    ${typePrefix} vB${typeSuffix}; { vB = " +
2043                     string(m_testParams.aggregate == 2 ? "${typePrefix}${typeSuffix}(data[${i1}][0],data[${i1}][1])" :
2044                                                          "data[${i1}]") +
2045                     "; }\n"
2046                     "    ${typePrefix} vC${typeSuffix}; { vC = " +
2047                     string(m_testParams.aggregate == 2 ? "${typePrefix}${typeSuffix}(data[${i2}][0],data[${i2}][1])" :
2048                                                          "data[${i2}]") +
2049                     "; }\n" +
2050                     string(m_testParams.testWithInterpolation ?
2051                                "    ${typePrefix} vIntrpV${typeSuffix}; { vIntrpV = " +
2052                                    string(m_testParams.aggregate == 2 ?
2053                                               "${typePrefix}${typeSuffix}(dataIntrp[0],dataIntrp[1])" :
2054                                               "dataIntrp") +
2055                                    "; }\n" :
2056                                "") +
2057                     string(m_testParams.testWithInterpolation ?
2058                                "    ${scalarName} vIntrp[${componentCount} / 3] = { ${arrivedIntrp} };\n" :
2059                                "") +
2060                     string(m_testParams.testWithFlatInterpolation ?
2061                                "    ${typePrefix} vFlatV${typeSuffix}; { vFlatV = " +
2062                                    string(m_testParams.aggregate == 2 ?
2063                                               "${typePrefix}${typeSuffix}(dataFlat[0],dataFlat[1])" :
2064                                               "dataFlat") +
2065                                    "; }\n" :
2066                                "") +
2067                     string(m_testParams.testWithFlatInterpolation ?
2068                                "    ${scalarName} vFlat[${componentCount} / 3] = { ${arrivedFlat}};\n" :
2069                                "")) +
2070         "\n"
2071         "    ${scalarName} v[${componentCount}] = { ${arrived} };\n" +
2072         "    uvec4 mask = uvec4(0);\n"
2073         "\n"
2074         "    for (int i = 0; i<${componentCount}; i++)\n"
2075         "        if (e[i] == v[i])\n"
2076         "            mask.x = mask.x | (1<<i);\n" +
2077         string(m_testParams.testWithInterpolation ? "    for (int i = 0; i<${componentCount} / 3; i++)\n" : "") +
2078         string(m_testParams.testWithInterpolation ? "        if (abs(eIntrp[i] - vIntrp[i]) < 0.001)\n" : "") +
2079         string(m_testParams.testWithInterpolation ? "            mask.y = mask.y | (1<<i);\n" : "") +
2080         string(m_testParams.testWithFlatInterpolation ? "    for (int i = 0; i<${componentCount} / 3; i++)\n" : "") +
2081         string(m_testParams.testWithFlatInterpolation ? "        if (eFlat[i] == vFlat[i])\n" : "") +
2082         string(m_testParams.testWithFlatInterpolation ? "            mask.z = mask.z | (1<<i);\n" : "") +
2083         "    out_color = mask;\n"
2084         "}\n");
2085 
2086     attributes["typePrefix"]      = typePrefix;
2087     attributes["typeSuffix"]      = typeSuffix;
2088     attributes["value"]           = value;
2089     attributes["componentCount"]  = de::toString(componentCount);
2090     attributes["expected"]        = expected;
2091     attributes["arrived"]         = arrived;
2092     attributes["expectedIntrp"]   = expectedIntrp;
2093     attributes["arrivedIntrp"]    = arrivedIntrp;
2094     attributes["expectedFlat"]    = expectedFlat;
2095     attributes["arrivedFlat"]     = arrivedFlat;
2096     attributes["scalarName"]      = scalarName;
2097     attributes["dataStruct"]      = dataStructType;
2098     attributes["dynamicIndexing"] = dynamicIndexing;
2099     attributes["primitiveId"]     = primitiveId;
2100     attributes["i0"]              = i0;
2101     attributes["i1"]              = i1;
2102     attributes["i2"]              = i2;
2103     attributes["vertexFormula0"]  = vertexFormula[0];
2104     attributes["vertexFormula1"]  = vertexFormula[1];
2105     attributes["vertexFormula2"]  = vertexFormula[2];
2106     attributes["intrpFormula"]    = intrpFormula;
2107 
2108     {
2109         size_t locationsPerInput = (m_testParams.aggregate > 0u ? m_testParams.aggregate : 1u);
2110 
2111         if (glu::isDataTypeDoubleOrDVec(m_testParams.dataType))
2112         {
2113             locationsPerInput *= 2;
2114         }
2115 
2116         size_t usedLocations = 0u;
2117         if (m_testParams.testWithInterpolation)
2118         {
2119             usedLocations += locationsPerInput;
2120             attributes["locInterp"] = de::toString(usedLocations);
2121         }
2122         if (m_testParams.testWithFlatInterpolation)
2123         {
2124             usedLocations += locationsPerInput;
2125             attributes["locFlat"] = de::toString(usedLocations);
2126         }
2127     }
2128 
2129     if (m_testParams.testWithFlatInterpolation)
2130     {
2131         attributes["vertexFormulaFlat"] = getDataProvokingVertexFormula();
2132     }
2133 
2134     if (isPrimitiveTopologyLine(m_testParams.topology))
2135     {
2136         DE_ASSERT(vertexFormula[2] == vertexFormula[1]);
2137     }
2138     else if (isPrimitiveTopologyPoint(m_testParams.topology))
2139     {
2140         DE_ASSERT(vertexFormula[2] == vertexFormula[1] && vertexFormula[1] == vertexFormula[0]);
2141     }
2142 
2143     if (m_testParams.useMeshShader)
2144         programCollection.glslSources.add("mesh") << glu::MeshSource(meshShader.specialize(attributes)) << buildOptions;
2145     else
2146         programCollection.glslSources.add("vert") << glu::VertexSource(vertShader.specialize(attributes));
2147 
2148     programCollection.glslSources.add("frag") << glu::FragmentSource(fragShader.specialize(attributes));
2149 
2150     if (m_testParams.provokingVertexLast && m_testParams.topology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP)
2151     {
2152         const bool provokingVertexLast = false;
2153 
2154         attributes["vertexFormula0"] = getDataVertexFormula(0, &provokingVertexLast);
2155         attributes["vertexFormula1"] = getDataVertexFormula(1, &provokingVertexLast);
2156         attributes["vertexFormula2"] = getDataVertexFormula(2, &provokingVertexLast);
2157 
2158         if (m_testParams.useMeshShader)
2159             programCollection.glslSources.add("mesh-forced")
2160                 << glu::VertexSource(meshShader.specialize(attributes)) << buildOptions;
2161         else
2162             programCollection.glslSources.add("vert-forced") << glu::VertexSource(vertShader.specialize(attributes));
2163 
2164         programCollection.glslSources.add("frag-forced") << glu::FragmentSource(fragShader.specialize(attributes));
2165     }
2166 
2167     if (m_testParams.testSubtype == TEST_SUBTYPE_TESS_SHADER)
2168         initMiscDataTessPrograms(programCollection, attributes);
2169     else if (m_testParams.testSubtype == TEST_SUBTYPE_GEOMETRY_SHADER)
2170         initMiscDataGeomPrograms(programCollection, attributes);
2171     else if (m_testParams.testSubtype == TEST_SUBTYPE_TESSGEOM_SHADER)
2172     {
2173         initMiscDataTessPrograms(programCollection, attributes);
2174         initMiscDataGeomPrograms(programCollection, attributes);
2175     }
2176 }
2177 
initMiscDataPrograms(SourceCollections & programCollection) const2178 void FragmentShadingBarycentricTestCase::initMiscDataPrograms(SourceCollections &programCollection) const
2179 {
2180     const std::string vertShader("#version 450\n"
2181                                  "#extension GL_EXT_fragment_shader_barycentric : require\n"
2182                                  "\n"
2183                                  "layout(location = 0) in  vec4 in_position;\n"
2184                                  "layout(location = 0) out uvec2 dataA;\n"
2185                                  "layout(location = 1) out uvec2 dataB;\n"
2186                                  "void main()\n"
2187                                  "{\n"
2188                                  // we will draw two triangles and we need to convert dataA for
2189                                  // second triangle to 0-2 range to simplify verification
2190                                  "    dataA       = uvec2(mod(gl_VertexIndex, 3));\n"
2191                                  "    dataB       = uvec2(7);\n"
2192                                  "    gl_Position = in_position;\n"
2193                                  "}\n");
2194     const std::string fragShader("#version 450\n"
2195                                  "#extension GL_EXT_fragment_shader_barycentric : require\n"
2196                                  "layout(location = 0) pervertexEXT in uvec2 dataA[];\n"
2197                                  "layout(location = 1) flat in uvec2 dataB;\n"
2198                                  "layout(location = 0) out uvec4 out_color;\n"
2199                                  "void main()\n"
2200                                  "{\n"
2201                                  // make sure that PerVertex decoration is only applied to location 0
2202                                  // and that the location 1 isn't compacted/remapped to location 0
2203                                  // by adding all values and making sure the result is 10
2204                                  "    out_color = uvec4(dataA[0].y + dataA[1].x + dataA[2].y + dataB.x);\n"
2205                                  "}\n");
2206 
2207     programCollection.glslSources.add("vert") << glu::VertexSource(vertShader);
2208     programCollection.glslSources.add("frag") << glu::FragmentSource(fragShader);
2209 }
2210 
initMiscDataTessPrograms(SourceCollections & programCollection,map<string,string> & attributes) const2211 void FragmentShadingBarycentricTestCase::initMiscDataTessPrograms(SourceCollections &programCollection,
2212                                                                   map<string, string> &attributes) const
2213 {
2214     // Tessellation control
2215     const tcu::StringTemplate tesc(
2216         string("#version 450\n"
2217                "#extension GL_EXT_tessellation_shader : require\n"
2218                "layout (vertices=6) out;\n"
2219                "in gl_PerVertex\n"
2220                "{\n"
2221                "    vec4 gl_Position;\n"
2222                "    float gl_PointSize;\n"
2223                "} gl_in[];\n"
2224                "out gl_PerVertex\n"
2225                "{\n"
2226                "    vec4 gl_Position;\n"
2227                "    float gl_PointSize;\n"
2228                "} gl_out[];\n"
2229                "\n"
2230                "${dataStruct}\n"
2231                "\n"
2232                "layout (location=0) in ${typePrefix} inData[]${typeSuffix};\n"
2233                "layout (location=0) out ${typePrefix} outData[]${typeSuffix};\n"
2234                "\n"
2235                "void main (void)\n"
2236                "{\n"
2237                "    if (gl_InvocationID == 0)\n"
2238                "    {\n"
2239                "        gl_TessLevelInner[0] = 1.0;\n"
2240                "        gl_TessLevelInner[1] = 1.0;\n"
2241                "        gl_TessLevelOuter[0] = 1.0;\n"
2242                "        gl_TessLevelOuter[1] = 1.0;\n"
2243                "        gl_TessLevelOuter[2] = 1.0;\n"
2244                "        gl_TessLevelOuter[3] = 1.0;\n"
2245                "    }\n"
2246                "    outData[gl_InvocationID] = inData[gl_InvocationID];\n"
2247                "    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
2248                "}\n"));
2249     programCollection.glslSources.add("tess_ctrl") << glu::TessellationControlSource(tesc.specialize(attributes));
2250 
2251     // Tessellation evaluation shader
2252     const tcu::StringTemplate tese(
2253         string("#version 450\n"
2254                "#extension GL_EXT_tessellation_shader : require\n"
2255                "layout (triangles) in;\n"
2256                "in gl_PerVertex\n"
2257                "{\n"
2258                "    vec4 gl_Position;\n"
2259                "    float gl_PointSize;\n"
2260                "} gl_in[];\n"
2261                "out gl_PerVertex\n"
2262                "{\n"
2263                "    vec4 gl_Position;\n"
2264                "    float gl_PointSize;\n"
2265                "};\n"
2266                "\n"
2267                "${dataStruct}\n"
2268                "\n"
2269                "layout (location=0) in ${typePrefix} inData[]${typeSuffix};\n"
2270                "struct OutDataStruct {uint idx; ${typePrefix} data${typeSuffix};};\n"
2271                "layout (location=0) flat out OutDataStruct outParam;\n"
2272                "\n"
2273                "void main (void)\n"
2274                "{\n"
2275                "    gl_Position = (gl_TessCoord.x * gl_in[0].gl_Position) +\n"
2276                "                  (gl_TessCoord.y * gl_in[1].gl_Position) +\n"
2277                "                  (gl_TessCoord.z * gl_in[2].gl_Position);\n"
2278                "    if (gl_TessCoord.xyz == vec3(0.0,1.0,0.0)) {outParam.idx = ${i2}; outParam.data = " +
2279                string(m_testParams.aggregate == 2 ? "${typePrefix}${typeSuffix}(inData[${i2}][0],inData[${i2}][1])" :
2280                                                     "inData[${i2}]") +
2281                "; }\n"
2282                "    else if (gl_TessCoord.xyz == vec3(1.0,0.0,0.0)) {outParam.idx = ${i0}; outParam.data = " +
2283                string(m_testParams.aggregate == 2 ? "${typePrefix}${typeSuffix}(inData[${i0}][0],inData[${i0}][1])" :
2284                                                     "inData[${i0}]") +
2285                "; }\n"
2286                "    else if (gl_TessCoord.xyz == vec3(0.0,0.0,1.0)) {outParam.idx = ${i1}; outParam.data = " +
2287                string(m_testParams.aggregate == 2 ? "${typePrefix}${typeSuffix}(inData[${i1}][0],inData[${i1}][1])" :
2288                                                     "inData[${i1}]") +
2289                "; }\n"
2290                "}\n"));
2291     programCollection.glslSources.add("tess_eval") << glu::TessellationEvaluationSource(tese.specialize(attributes));
2292 }
2293 
initMiscDataGeomPrograms(SourceCollections & programCollection,map<string,string> & attributes) const2294 void FragmentShadingBarycentricTestCase::initMiscDataGeomPrograms(SourceCollections &programCollection,
2295                                                                   map<string, string> &attributes) const
2296 {
2297     // Geometry shader
2298     const tcu::StringTemplate geom(string("#version 460\n"
2299                                           "\n"
2300                                           "layout (triangles) in;\n"
2301                                           "layout (triangle_strip, max_vertices=3) out;\n"
2302                                           "in gl_PerVertex\n"
2303                                           "{\n"
2304                                           "    vec4 gl_Position;\n"
2305                                           "    float gl_PointSize;\n"
2306                                           "} gl_in[3];\n"
2307                                           "out gl_PerVertex\n"
2308                                           "{\n"
2309                                           "    vec4 gl_Position;\n"
2310                                           "    float gl_PointSize;\n"
2311                                           "};\n"
2312                                           "\n"
2313                                           "${dataStruct}\n"
2314                                           "\n") +
2315                                    string(((m_testParams.testSubtype == TEST_SUBTYPE_TESS_SHADER) ||
2316                                            (m_testParams.testSubtype == TEST_SUBTYPE_TESSGEOM_SHADER)) ?
2317                                               "struct InOutDataStruct {uint idx; ${typePrefix} data${typeSuffix};};\n"
2318                                               "layout(location = 0) in InOutDataStruct inParam[];\n" :
2319                                               "layout (location=0) in ${typePrefix} inData[]${typeSuffix};\n") +
2320                                    string(((m_testParams.testSubtype == TEST_SUBTYPE_TESS_SHADER) ||
2321                                            (m_testParams.testSubtype == TEST_SUBTYPE_TESSGEOM_SHADER)) ?
2322                                               "layout (location=0) flat out InOutDataStruct outParam;\n" :
2323                                               "layout (location=0) out ${typePrefix} outData${typeSuffix};\n") +
2324                                    string("\n"
2325                                           "void main ()\n"
2326                                           "{\n"
2327                                           "    gl_Position = gl_in[0].gl_Position;\n") +
2328                                    string(((m_testParams.testSubtype == TEST_SUBTYPE_TESS_SHADER) ||
2329                                            (m_testParams.testSubtype == TEST_SUBTYPE_TESSGEOM_SHADER)) ?
2330                                               "    outParam = inParam[${i0}];\n" :
2331                                               "    outData = inData[${i0}];\n") +
2332                                    string("    EmitVertex();\n"
2333 
2334                                           "    gl_Position = gl_in[1].gl_Position;\n") +
2335                                    string(((m_testParams.testSubtype == TEST_SUBTYPE_TESS_SHADER) ||
2336                                            (m_testParams.testSubtype == TEST_SUBTYPE_TESSGEOM_SHADER)) ?
2337                                               "    outParam = inParam[${i1}];\n" :
2338                                               "    outData = inData[${i1}];\n") +
2339                                    string("    EmitVertex();\n"
2340 
2341                                           "    gl_Position = gl_in[2].gl_Position;\n") +
2342                                    string(((m_testParams.testSubtype == TEST_SUBTYPE_TESS_SHADER) ||
2343                                            (m_testParams.testSubtype == TEST_SUBTYPE_TESSGEOM_SHADER)) ?
2344                                               "    outParam = inParam[${i2}];\n" :
2345                                               "    outData = inData[${i2}];\n") +
2346                                    string("    EmitVertex();\n"
2347                                           "}\n"));
2348     programCollection.glslSources.add("geom") << glu::GeometrySource(geom.specialize(attributes));
2349 }
2350 
generateWeightMeshShader(void) const2351 string FragmentShadingBarycentricTestCase::generateWeightMeshShader(void) const
2352 {
2353 
2354     string meshShader;
2355 
2356     switch (m_testParams.topology)
2357     {
2358     case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
2359     {
2360         meshShader =
2361             "#version 450\n"
2362             "#extension GL_EXT_mesh_shader : enable\n"
2363             "\n"
2364             "layout(local_size_x = 8, local_size_y = 4, local_size_z = 1) in;\n"
2365             "layout(triangles) out;\n"
2366             "layout(max_vertices=256, max_primitives=256) out;\n"
2367             "layout(push_constant) uniform PushConstant { mat4 mvp; } pc;\n"
2368             "\n"
2369             "layout(set = 0, binding = 0) buffer PerVertexData{ \n"
2370             "    vec4 vertexBuffer[12];\n"
2371             "} pvd;\n"
2372             "layout (location=0) out vec3 outColor[];\n"
2373             "\n"
2374             "void main ()\n"
2375             "{\n"
2376             "    uint maxVertex = 6;\n"
2377             "    uint maxPrimitive = 2;\n"
2378             "    SetMeshOutputsEXT(maxVertex, maxPrimitive);\n"
2379             "    const uint vertex = gl_LocalInvocationIndex;\n"
2380             "    const uint primitive = gl_LocalInvocationIndex;\n"
2381             "    const uvec3 indices[2] = uvec3[](\n"
2382             "        uvec3(0, 1, 2),\n"
2383             "        uvec3(3, 4, 5)\n"
2384             "    );\n"
2385             "    if (vertex < maxVertex)\n"
2386             "    {\n"
2387             "        gl_MeshVerticesEXT[vertex].gl_Position = transpose(pc.mvp) * pvd.vertexBuffer[vertex*2];\n"
2388             "        outColor[vertex] = pvd.vertexBuffer[vertex*2+1].xyz;\n"
2389             "    }\n"
2390             "    if(primitive < maxPrimitive){\n"
2391             "        gl_PrimitiveTriangleIndicesEXT[primitive] = indices[primitive];\n"
2392             "    }\n"
2393             "}\n";
2394 
2395         return meshShader;
2396     }
2397     case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
2398     {
2399         meshShader =
2400             "#version 450\n"
2401             "#extension GL_EXT_mesh_shader : enable\n"
2402             "\n"
2403             "layout(local_size_x = 8, local_size_y = 4, local_size_z = 1) in;\n"
2404             "layout(lines) out;\n"
2405             "layout(max_vertices=256, max_primitives=256) out;\n"
2406             "layout(push_constant) uniform PushConstant { mat4 mvp; } pc;\n"
2407             "\n"
2408             "layout(set = 0, binding = 0) buffer PerVertexData{ \n"
2409             "    vec4 vertexBuffer[512];\n"
2410             "} pvd;\n"
2411             "layout (location=0) out vec3 outColor[];\n"
2412             "\n"
2413             "void main ()\n"
2414             "{\n"
2415             "    uint maxVertex = 256;\n"
2416             "    uint maxPrimitive = 128;\n"
2417             "    SetMeshOutputsEXT(maxVertex, maxPrimitive);\n"
2418             "    uint iterations = max(maxVertex, maxPrimitive) / (8 * 4 * 1);\n"
2419             "    for (int  iteration = 0; iteration < iterations; ++iteration)\n"
2420             "    {\n"
2421             "        const uint vertex = gl_LocalInvocationIndex * iterations + iteration;\n"
2422             "        const uint primitive = gl_LocalInvocationIndex * iterations + iteration;\n"
2423             "        if (vertex < maxVertex)\n"
2424             "        {\n"
2425             "             gl_MeshVerticesEXT[vertex].gl_Position = transpose(pc.mvp) * pvd.vertexBuffer[vertex*2];\n"
2426             "             outColor[vertex] = pvd.vertexBuffer[vertex*2+1].xyz;\n"
2427             "        }\n"
2428             "        if(primitive < maxPrimitive){\n"
2429             "             gl_PrimitiveLineIndicesEXT[primitive] = uvec2(primitive*2, primitive*2+1);\n"
2430             "        }\n"
2431             "    }\n"
2432             "}\n";
2433 
2434         return meshShader;
2435     }
2436     case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
2437     {
2438         meshShader = "#version 450\n"
2439                      "#extension GL_EXT_mesh_shader : enable\n"
2440                      "\n"
2441                      "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
2442                      "layout(points) out;\n"
2443                      "layout(max_vertices=1, max_primitives = 1) out;\n"
2444                      "layout(push_constant) uniform PushConstant { mat4 mvp; } pc;\n"
2445                      "\n"
2446                      "layout(set = 0, binding = 0) buffer PerVertexData{ \n"
2447                      "    vec4 vertexBuffer[32768];\n"
2448                      "} pvd;\n"
2449                      "layout (location=0) out vec3 outColor[];\n"
2450                      "\n"
2451                      "void main ()\n"
2452                      "{\n"
2453                      "    uint maxVertex = 1;\n"
2454                      "    uint maxPrimitive = 1;\n"
2455                      "    SetMeshOutputsEXT(maxVertex, maxPrimitive);\n"
2456                      "    const uint vertex = gl_LocalInvocationIndex;\n"
2457                      "    const uint primitive = gl_LocalInvocationIndex;\n"
2458                      "    const uint workGroupIndex = gl_NumWorkGroups.x * gl_NumWorkGroups.y * gl_WorkGroupID.z + "
2459                      "gl_NumWorkGroups.x * gl_WorkGroupID.y + gl_WorkGroupID.x;\n"
2460                      "    uint jobId = workGroupIndex + gl_LocalInvocationIndex;\n"
2461                      "    gl_MeshVerticesEXT[vertex].gl_Position = transpose(pc.mvp) * pvd.vertexBuffer[jobId*2];\n"
2462                      "    outColor[vertex] = pvd.vertexBuffer[jobId*2+1].xyz;\n"
2463                      "    gl_PrimitivePointIndicesEXT[primitive] = primitive;\n"
2464                      "}\n";
2465 
2466         return meshShader;
2467     }
2468     default:
2469         TCU_THROW(InternalError, "Unknown topology");
2470     }
2471 }
2472 
initWeightPrograms(SourceCollections & programCollection) const2473 void FragmentShadingBarycentricTestCase::initWeightPrograms(SourceCollections &programCollection) const
2474 {
2475     const string baryCoordVariable = m_testParams.perspective ? "BaryCoord" : "BaryCoordNoPersp";
2476     const string declspecRef       = m_testParams.perspective ? "smooth" : "noperspective";
2477     const ShaderBuildOptions buildOptions(programCollection.usedVulkanVersion, SPIRV_VERSION_1_4, 0u);
2478 
2479     string meshShader;
2480 
2481     if (m_testParams.useMeshShader)
2482         meshShader = generateWeightMeshShader();
2483 
2484     const string vertShader = "#version 450\n"
2485                               "\n"
2486                               "layout(location = 0) in  vec4 in_position;\n"
2487                               "layout(location = 1) in  vec4 in_color;\n"
2488                               "layout(location = 0) out vec3 color;\n"
2489                               "layout(push_constant) uniform PushConstant { mat4 mvp; } pc;\n"
2490                               "\n"
2491                               "void main()\n"
2492                               "{\n"
2493                               "    color        = in_color.xyz;\n"
2494                               "    gl_Position  = transpose(pc.mvp) * in_position;\n"
2495                               "    gl_PointSize = 1.0;\n"
2496                               "}\n";
2497     const tcu::StringTemplate fragShaderReference("#version 450\n"
2498                                                   "\n"
2499                                                   "layout(location = 0) ${glslDeclspecRef} in vec3 in_color;\n"
2500                                                   "layout(location = 0) out vec4 out_color;\n"
2501                                                   "\n"
2502                                                   "void main()\n"
2503                                                   "{\n"
2504                                                   "    out_color = vec4(in_color, 1.0f);\n"
2505                                                   "}\n");
2506     const tcu::StringTemplate fragShaderTestGLSL(
2507         "#version 450\n"
2508         "#extension GL_EXT_fragment_shader_barycentric : require\n"
2509         "\n"
2510         "layout(location = 0) pervertexEXT in vec3 in_color[];\n"
2511         "layout(location = 0) out vec4 out_color;\n"
2512         "\n"
2513         "void main()\n"
2514         "{\n"
2515         "    vec3 bc = ${glslFormulaeTest};\n"
2516         "    out_color = vec4(in_color[0] * bc.x + in_color[1] * bc.y + in_color[2] * bc.z, 1.0f);\n"
2517         "}\n");
2518 
2519     // it is not possible to add centroid/sample qualifiers to gl_BaryCoordEXT/gl_BaryCoordNoPerspEXT
2520     // but it is possible to do this with SPIR-V - code below is a slightly modified version of fragShaderTestGLSL
2521     const tcu::StringTemplate fragShaderTestSPIRV("OpCapability Shader\n"
2522                                                   "OpCapability FragmentBarycentricKHR\n"
2523                                                   "${spirvAdditionalCapabilities}"
2524                                                   "OpExtension \"SPV_KHR_fragment_shader_barycentric\"\n"
2525                                                   "%1 = OpExtInstImport \"GLSL.std.450\"\n"
2526                                                   "OpMemoryModel Logical GLSL450\n"
2527                                                   "OpEntryPoint Fragment %4 \"main\" %var_BaryCoord %15 %20\n"
2528                                                   "OpExecutionMode %4 OriginUpperLeft\n"
2529                                                   "OpDecorate %var_BaryCoord BuiltIn ${spirvBaryCoordVariable}\n"
2530                                                   "OpDecorate %var_BaryCoord ${spirvBaryCoordDecoration}\n"
2531                                                   "OpDecorate %15 Location 0\n"
2532                                                   "OpDecorate %20 Location 0\n"
2533                                                   "OpDecorate %20 PerVertexKHR\n"
2534                                                   "%2 = OpTypeVoid\n"
2535                                                   "%3 = OpTypeFunction %2\n"
2536                                                   "%6 = OpTypeFloat 32\n"
2537                                                   "%7 = OpTypeVector %6 3\n"
2538                                                   "%8 = OpTypePointer Function %7\n"
2539                                                   "%10 = OpTypePointer Input %7\n"
2540                                                   "%var_BaryCoord = OpVariable %10 Input\n"
2541                                                   "%13 = OpTypeVector %6 4\n"
2542                                                   "%14 = OpTypePointer Output %13\n"
2543                                                   "%15 = OpVariable %14 Output\n"
2544                                                   "%16 = OpTypeInt 32 0\n"
2545                                                   "%17 = OpConstant %16 3\n"
2546                                                   "%18 = OpTypeArray %7 %17\n"
2547                                                   "%19 = OpTypePointer Input %18\n"
2548                                                   "%20 = OpVariable %19 Input\n"
2549                                                   "%21 = OpTypeInt 32 1\n"
2550                                                   "%22 = OpConstant %21 0\n"
2551                                                   "%25 = OpConstant %16 0\n"
2552                                                   "%26 = OpTypePointer Function %6\n"
2553                                                   "%30 = OpConstant %21 1\n"
2554                                                   "%33 = OpConstant %16 1\n"
2555                                                   "%38 = OpConstant %21 2\n"
2556                                                   "%41 = OpConstant %16 2\n"
2557                                                   "%46 = OpConstant %6 1\n"
2558                                                   "%4 = OpFunction %2 None %3\n"
2559                                                   "%5 = OpLabel\n"
2560                                                   "%9 = OpVariable %8 Function\n"
2561                                                   "%12 = OpLoad %7 %var_BaryCoord\n"
2562                                                   "OpStore %9 %12\n"
2563                                                   "%23 = OpAccessChain %10 %20 %22\n"
2564                                                   "%24 = OpLoad %7 %23\n"
2565                                                   "%27 = OpAccessChain %26 %9 %25\n"
2566                                                   "%28 = OpLoad %6 %27\n"
2567                                                   "%29 = OpVectorTimesScalar %7 %24 %28\n"
2568                                                   "%31 = OpAccessChain %10 %20 %30\n"
2569                                                   "%32 = OpLoad %7 %31\n"
2570                                                   "%34 = OpAccessChain %26 %9 %33\n"
2571                                                   "%35 = OpLoad %6 %34\n"
2572                                                   "%36 = OpVectorTimesScalar %7 %32 %35\n"
2573                                                   "%37 = OpFAdd %7 %29 %36\n"
2574                                                   "%39 = OpAccessChain %10 %20 %38\n"
2575                                                   "%40 = OpLoad %7 %39\n"
2576                                                   "%42 = OpAccessChain %26 %9 %41\n"
2577                                                   "%43 = OpLoad %6 %42\n"
2578                                                   "%44 = OpVectorTimesScalar %7 %40 %43\n"
2579                                                   "%45 = OpFAdd %7 %37 %44\n"
2580                                                   "%47 = OpCompositeExtract %6 %45 0\n"
2581                                                   "%48 = OpCompositeExtract %6 %45 1\n"
2582                                                   "%49 = OpCompositeExtract %6 %45 2\n"
2583                                                   "%50 = OpCompositeConstruct %13 %47 %48 %49 %46\n"
2584                                                   "OpStore %15 %50\n"
2585                                                   "OpReturn\n"
2586                                                   "OpFunctionEnd\n");
2587 
2588     // use single specialization map for test and reference fragment shaders
2589     // as well as for spirv version of test shader
2590     map<string, string> attributes{{"glslDeclspecRef", declspecRef}};
2591 
2592     switch (m_testParams.testSubtype)
2593     {
2594     case TEST_SUBTYPE_MSAA_INTERPOLATE_AT_CENTROID:
2595         attributes["glslFormulaeTest"] = std::string("interpolateAtCentroid(gl_") + baryCoordVariable + "EXT)";
2596         attributes["glslDeclspecRef"] += " centroid";
2597         break;
2598     case TEST_SUBTYPE_MSAA_INTERPOLATE_AT_SAMPLE:
2599         attributes["glslFormulaeTest"] =
2600             std::string("interpolateAtSample(gl_") + baryCoordVariable + "EXT, gl_SampleID)";
2601         attributes["glslDeclspecRef"] += " sample";
2602         break;
2603     case TEST_SUBTYPE_MSAA_INTERPOLATE_AT_OFFSET:
2604         attributes["glslFormulaeTest"] =
2605             std::string("interpolateAtOffset(gl_") + baryCoordVariable + "EXT, vec2(gl_SamplePosition - vec2(0.5)))";
2606         attributes["glslDeclspecRef"] += " sample";
2607         break;
2608     case TEST_SUBTYPE_MSAA_CENTROID_QUALIFIER:
2609         attributes["spirvBaryCoordVariable"]      = baryCoordVariable + "KHR";
2610         attributes["spirvBaryCoordDecoration"]    = "Centroid";
2611         attributes["spirvAdditionalCapabilities"] = "";
2612         attributes["glslDeclspecRef"] += " centroid";
2613         break;
2614     case TEST_SUBTYPE_MSAA_SAMPLE_QUALIFIER:
2615         attributes["spirvBaryCoordVariable"]      = baryCoordVariable + "KHR";
2616         attributes["spirvBaryCoordDecoration"]    = "Sample";
2617         attributes["spirvAdditionalCapabilities"] = "OpCapability SampleRateShading\n";
2618         attributes["glslDeclspecRef"] += " sample";
2619         break;
2620     default:
2621         attributes["glslFormulaeTest"] = std::string("gl_") + baryCoordVariable + "EXT";
2622         break;
2623     }
2624 
2625     if (m_testParams.useMeshShader)
2626         programCollection.glslSources.add("mesh") << glu::MeshSource(meshShader) << buildOptions;
2627     else
2628         programCollection.glslSources.add("vert") << glu::VertexSource(vertShader);
2629 
2630     programCollection.glslSources.add("frag_reference")
2631         << glu::FragmentSource(fragShaderReference.specialize(attributes));
2632 
2633     // use "spirvBaryCoordVariable" key to determine if we should use glsl or spir-v version of test shader
2634     if (attributes.count("spirvBaryCoordVariable"))
2635         programCollection.spirvAsmSources.add("frag_test") << fragShaderTestSPIRV.specialize(attributes);
2636     else
2637         programCollection.glslSources.add("frag_test")
2638             << glu::FragmentSource(fragShaderTestGLSL.specialize(attributes));
2639 }
2640 } // namespace
2641 
createTests(tcu::TestContext & testCtx,const std::string & name)2642 tcu::TestCaseGroup *createTests(tcu::TestContext &testCtx, const std::string &name)
2643 {
2644     const bool notused = false;
2645     MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, name.c_str()));
2646     // Tests using graphics pipeline libraries
2647     MovePtr<tcu::TestCaseGroup> libGroup(new tcu::TestCaseGroup(testCtx, "pipeline_library"));
2648     // Tests using graphics pipeline libraries with fast linking
2649     MovePtr<tcu::TestCaseGroup> fastLinkGroup(new tcu::TestCaseGroup(testCtx, "fast_linked_library"));
2650 
2651     const struct
2652     {
2653         PipelineConstructionType constructionType;
2654         tcu::TestCaseGroup *testGroup;
2655     } constructionTypeCases[] = {
2656         {PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC, group.get()},
2657         {PIPELINE_CONSTRUCTION_TYPE_LINK_TIME_OPTIMIZED_LIBRARY, libGroup.get()},
2658         {PIPELINE_CONSTRUCTION_TYPE_FAST_LINKED_LIBRARY, fastLinkGroup.get()},
2659     };
2660 
2661     const struct PrimitiveTestSpec
2662     {
2663         VkPrimitiveTopology topology;
2664         const char *name;
2665     } topologies[] = {
2666         {VK_PRIMITIVE_TOPOLOGY_POINT_LIST, "point_list"},
2667         {VK_PRIMITIVE_TOPOLOGY_LINE_LIST, "line_list"},
2668         {VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, "line_strip"},
2669         {VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, "triangle_list"},
2670         {VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, "triangle_strip"},
2671         {VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN, "triangle_fan"},
2672         {VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY, "line_list_with_adjacency"},
2673         {VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY, "line_strip_with_adjacency"},
2674         {VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY, "triangle_list_with_adjacency"},
2675         {VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY, "triangle_strip_with_adjacency"},
2676     };
2677     const struct ClipVerticesTestSpec
2678     {
2679         bool clip;
2680         const char *name;
2681     } clipVerticesSpecs[] = {
2682         {false, "no_clip"},
2683         {true, "clip"},
2684     };
2685     const struct useMeshShaderTestSpec
2686     {
2687         bool meshShader;
2688         const char *name;
2689     } useMeshShaderSpecs[] = {
2690         {true, "mesh_shader"},
2691         {false, "vertex_shader"},
2692     };
2693     const glu::DataType dataTypes[] = {
2694         glu::TYPE_FLOAT,  glu::TYPE_FLOAT_VEC2,  glu::TYPE_FLOAT_VEC3,  glu::TYPE_FLOAT_VEC4,
2695         glu::TYPE_DOUBLE, glu::TYPE_DOUBLE_VEC2, glu::TYPE_DOUBLE_VEC3, glu::TYPE_DOUBLE_VEC4,
2696         glu::TYPE_INT,    glu::TYPE_INT_VEC2,    glu::TYPE_INT_VEC3,    glu::TYPE_INT_VEC4,
2697         glu::TYPE_UINT,   glu::TYPE_UINT_VEC2,   glu::TYPE_UINT_VEC3,   glu::TYPE_UINT_VEC4,
2698     };
2699     const struct Perspective
2700     {
2701         const char *name;
2702         bool value;
2703     } perspectives[] = {
2704         {"perspective", true},
2705         {"noperspective", false},
2706     };
2707     const struct DynamicIndexing
2708     {
2709         const char *name;
2710         bool value;
2711     } dynamicIndexings[] = {
2712         {"static", false},
2713         {"dynamic", true},
2714     };
2715     const struct ProvokingVertex
2716     {
2717         const char *name;
2718         bool value;
2719     } provokingVertices[] = {
2720         {"provoking_first", false},
2721         {"provoking_last", true},
2722     };
2723     const uint32_t rotations[] = {0, 85, 95};
2724     const struct TopologyInPipeline
2725     {
2726         const char *name;
2727         bool value;
2728     } topologiesInPipeline[] = {
2729         {"pipeline_topology_static", false},
2730         {"pipeline_topology_dynamic", true},
2731     };
2732     const struct InterpolationTypes
2733     {
2734         const char *name;
2735         bool testWithInterpolation;
2736         bool testWithFlatInterpolation;
2737     } interpolationTypes[] = {
2738         {"per_vertex", false, false}, {"per_vertex_interp", true, false}, {"per_vertex_flat", false, true}};
2739 
2740     for (const auto &constructionTypeCase : constructionTypeCases)
2741     {
2742         MovePtr<tcu::TestCaseGroup> testTypeGroup(new tcu::TestCaseGroup(testCtx, "data"));
2743         const TestType testType = TEST_TYPE_DATA;
2744 
2745         for (size_t provokingVertexNdx = 0; provokingVertexNdx < DE_LENGTH_OF_ARRAY(provokingVertices);
2746              ++provokingVertexNdx)
2747         {
2748             MovePtr<tcu::TestCaseGroup> provokingVertexGroup(
2749                 new tcu::TestCaseGroup(testCtx, provokingVertices[provokingVertexNdx].name));
2750             const bool provokingVertexLast = provokingVertices[provokingVertexNdx].value;
2751 
2752             for (size_t dynamicNdx = 0; dynamicNdx < DE_LENGTH_OF_ARRAY(dynamicIndexings); ++dynamicNdx)
2753             {
2754                 MovePtr<tcu::TestCaseGroup> dynamicIndexingGroup(
2755                     new tcu::TestCaseGroup(testCtx, dynamicIndexings[dynamicNdx].name));
2756                 const bool dynamicIndexing = dynamicIndexings[dynamicNdx].value;
2757 
2758                 for (size_t topologyNdx = 0; topologyNdx < DE_LENGTH_OF_ARRAY(topologies); ++topologyNdx)
2759                 {
2760                     MovePtr<tcu::TestCaseGroup> topologyGroup(
2761                         new tcu::TestCaseGroup(testCtx, topologies[topologyNdx].name));
2762                     const VkPrimitiveTopology topology = topologies[topologyNdx].topology;
2763 
2764                     for (size_t clipVerticesSpecNdx = 0; clipVerticesSpecNdx < DE_LENGTH_OF_ARRAY(clipVerticesSpecs);
2765                          ++clipVerticesSpecNdx)
2766                     {
2767                         MovePtr<tcu::TestCaseGroup> clipVerticesGroup(
2768                             new tcu::TestCaseGroup(testCtx, clipVerticesSpecs[clipVerticesSpecNdx].name, ""));
2769                         const bool clipVertices = clipVerticesSpecs[clipVerticesSpecNdx].clip;
2770 
2771                         if (clipVertices && topology != VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
2772                             // no implemented
2773                             continue;
2774 
2775                         for (size_t aggregateNdx = 0; aggregateNdx < 3; ++aggregateNdx)
2776                         {
2777                             const string aggregateName = aggregateNdx == 0 ? "type" :
2778                                                          aggregateNdx == 1 ? "struct" :
2779                                                                              "array" + de::toString(aggregateNdx);
2780                             MovePtr<tcu::TestCaseGroup> aggregateGroup(
2781                                 new tcu::TestCaseGroup(testCtx, aggregateName.c_str()));
2782 
2783                             for (size_t dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(dataTypes); ++dataTypeNdx)
2784                             {
2785                                 const glu::DataType dataType = dataTypes[dataTypeNdx];
2786 
2787                                 MovePtr<tcu::TestCaseGroup> dataTypeGroup(
2788                                     new tcu::TestCaseGroup(testCtx, getDataTypeName(dataType), ""));
2789 
2790                                 for (size_t interpolationTypeNdx = 0;
2791                                      interpolationTypeNdx < DE_LENGTH_OF_ARRAY(interpolationTypes);
2792                                      ++interpolationTypeNdx)
2793                                 {
2794                                     MovePtr<tcu::TestCaseGroup> interpolationTypeGroup(new tcu::TestCaseGroup(
2795                                         testCtx, interpolationTypes[interpolationTypeNdx].name, ""));
2796 
2797                                     if (interpolationTypes[interpolationTypeNdx].testWithInterpolation &&
2798                                         (glu::isDataTypeIntOrIVec(dataType) || glu::isDataTypeUintOrUVec(dataType) ||
2799                                          glu::isDataTypeDoubleOrDVec(dataType)))
2800                                     {
2801                                         // integer and double inputs must be qualified as flat, cannot be interpolated
2802                                         continue;
2803                                     }
2804 
2805                                     for (size_t useMeshShaderSpecNdx = 0;
2806                                          useMeshShaderSpecNdx < DE_LENGTH_OF_ARRAY(useMeshShaderSpecs);
2807                                          ++useMeshShaderSpecNdx)
2808                                     {
2809                                         const bool useMeshShader = useMeshShaderSpecs[useMeshShaderSpecNdx].meshShader;
2810                                         const char *useMeshShaderName = useMeshShaderSpecs[useMeshShaderSpecNdx].name;
2811 
2812                                         if (useMeshShader && !(topology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST ||
2813                                                                topology == VK_PRIMITIVE_TOPOLOGY_LINE_LIST ||
2814                                                                topology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST))
2815                                             // mesh shader support only for point, line or triangle list topology
2816                                             continue;
2817 
2818                                         const TestParams testParams = {
2819                                             constructionTypeCase.constructionType,
2820                                             testType,              //  TestType testType;
2821                                             TEST_SUBTYPE_DEFAULT,  //  TestSubtype testSubtype;
2822                                             topology,              //  VkPrimitiveTopology topology;
2823                                             dynamicIndexing,       //  bool dynamicIndexing;
2824                                             aggregateNdx,          //  size_t aggregate;
2825                                             dataType,              //  glu::DataType dataType;
2826                                             DATA_TEST_WIDTH,       //  uint32_t width;
2827                                             DATA_TEST_HEIGHT,      //  uint32_t height;
2828                                             notused,               //  bool perspective;
2829                                             provokingVertexLast,   //  bool provokingVertexLast;
2830                                             (uint32_t)notused,     //  uint32_t rotation;
2831                                             notused,               //  bool                dynamicTopologyInPipeline
2832                                             VK_SAMPLE_COUNT_1_BIT, //  VkSampleCountFlagBits sampleCount;
2833                                             interpolationTypes[interpolationTypeNdx]
2834                                                 .testWithInterpolation, //  bool                testWithInterpolation
2835                                             interpolationTypes[interpolationTypeNdx]
2836                                                 .testWithFlatInterpolation, //  bool                testWithFlatInterpolation
2837                                             clipVertices,                   //  bool                clipVertices
2838                                             useMeshShader,                  //  bool                useMeshShader
2839                                         };
2840                                         interpolationTypeGroup->addChild(new FragmentShadingBarycentricTestCase(
2841                                             testCtx, useMeshShaderName, testParams));
2842                                     }
2843 
2844                                     dataTypeGroup->addChild(interpolationTypeGroup.release());
2845                                 }
2846                                 aggregateGroup->addChild(dataTypeGroup.release());
2847                             }
2848 
2849                             clipVerticesGroup->addChild(aggregateGroup.release());
2850                         }
2851                         topologyGroup->addChild(clipVerticesGroup.release());
2852                     }
2853 
2854                     dynamicIndexingGroup->addChild(topologyGroup.release());
2855                 }
2856 
2857                 provokingVertexGroup->addChild(dynamicIndexingGroup.release());
2858             }
2859 
2860             testTypeGroup->addChild(provokingVertexGroup.release());
2861         }
2862 
2863         {
2864             MovePtr<tcu::TestCaseGroup> miscGroup(new tcu::TestCaseGroup(testCtx, "misc"));
2865             const TestParams testParams{
2866                 constructionTypeCase.constructionType,
2867                 TEST_TYPE_DATA,                      //  TestType testType;
2868                 TEST_SUBTYPE_PERVERTEX_CORRECTNESS,  //  TestSubtype testSubtype;
2869                 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, //  VkPrimitiveTopology topology;
2870                 notused,                             //  bool dynamicIndexing;
2871                 notused,                             //  size_t aggregate;
2872                 glu::TYPE_FLOAT_VEC2,                //  glu::DataType dataType;
2873                 DATA_TEST_WIDTH,                     //  uint32_t width;
2874                 DATA_TEST_HEIGHT,                    //  uint32_t height;
2875                 notused,                             //  bool perspective;
2876                 notused,                             //  bool provokingVertexLast;
2877                 (uint32_t)notused,                   //  uint32_t rotation;
2878                 notused,                             //  bool                    dynamicTopologyInPipeline
2879                 VK_SAMPLE_COUNT_1_BIT,               //  VkSampleCountFlagBits sampleCount;
2880                 false,                               //  bool                    testWithInterpolation
2881                 false,                               //    bool                    testWithFlatInterpolation
2882                 false,                               //    bool                    clipVertices
2883                 false,                               //  bool                    useMeshShader
2884             };
2885             miscGroup->addChild(new FragmentShadingBarycentricTestCase(testCtx, "pervertex_correctness", testParams));
2886             testTypeGroup->addChild(miscGroup.release());
2887         }
2888 
2889         {
2890             MovePtr<tcu::TestCaseGroup> scGroup(new tcu::TestCaseGroup(testCtx, "shader_combos"));
2891             for (uint32_t testSubType = (uint32_t)TEST_SUBTYPE_TESS_SHADER;
2892                  testSubType <= (uint32_t)TEST_SUBTYPE_TESSGEOM_SHADER; testSubType++)
2893             {
2894                 VkPrimitiveTopology primitiveType = (((TestSubtype)testSubType) == TEST_SUBTYPE_GEOMETRY_SHADER) ?
2895                                                         VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST :
2896                                                         VK_PRIMITIVE_TOPOLOGY_PATCH_LIST;
2897                 const std::string shaderComboName = getShaderComboName(testSubType);
2898 
2899                 MovePtr<tcu::TestCaseGroup> scSubGroup(new tcu::TestCaseGroup(testCtx, shaderComboName.c_str()));
2900 
2901                 for (size_t aggregateNdx = 0; aggregateNdx < 3; ++aggregateNdx)
2902                 {
2903                     const string aggregateName = aggregateNdx == 0 ? "type" :
2904                                                  aggregateNdx == 1 ? "struct" :
2905                                                                      "array" + de::toString(aggregateNdx);
2906                     MovePtr<tcu::TestCaseGroup> aggregateGroup(new tcu::TestCaseGroup(testCtx, aggregateName.c_str()));
2907 
2908                     for (size_t dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(dataTypes); ++dataTypeNdx)
2909                     {
2910                         const glu::DataType dataType = dataTypes[dataTypeNdx];
2911                         const char *dataTypeName     = getDataTypeName(dataType);
2912 
2913                         const TestParams testParamsShaders{
2914                             constructionTypeCase.constructionType,
2915                             TEST_TYPE_DATA,           //  TestType testType;
2916                             (TestSubtype)testSubType, //  TestSubtype testSubtype;
2917                             primitiveType,            //  VkPrimitiveTopology topology;
2918                             notused,                  //  bool dynamicIndexing;
2919                             aggregateNdx,             //  size_t aggregate;
2920                             dataType,                 //  glu::DataType dataType;
2921                             DATA_TEST_WIDTH,          //  uint32_t width;
2922                             DATA_TEST_HEIGHT,         //  uint32_t height;
2923                             notused,                  //  bool perspective;
2924                             notused,                  //  bool provokingVertexLast;
2925                             (uint32_t)notused,        //  uint32_t rotation;
2926                             notused,                  //  bool                    dynamicTopologyInPipeline
2927                             VK_SAMPLE_COUNT_1_BIT,    //  VkSampleCountFlagBits sampleCount;
2928                             false,                    //  bool                    testWithInterpolation
2929                             false,                    //    bool                    testWithFlatInterpolation
2930                             false,                    //    bool                    clipVertices
2931                             false,                    //  bool                    useMeshShader
2932                         };
2933                         aggregateGroup->addChild(
2934                             new FragmentShadingBarycentricTestCase(testCtx, dataTypeName, testParamsShaders));
2935                     }
2936                     scSubGroup->addChild(aggregateGroup.release());
2937                 }
2938                 scGroup->addChild(scSubGroup.release());
2939             }
2940             testTypeGroup->addChild(scGroup.release());
2941         }
2942 
2943         constructionTypeCase.testGroup->addChild(testTypeGroup.release());
2944     }
2945 
2946     for (const auto &constructionTypeCase : constructionTypeCases)
2947     {
2948         const struct MsaaTestCase
2949         {
2950             const char *name;
2951             VkSampleCountFlagBits samples;
2952             TestSubtype subtype;
2953         } msaaCases[] = {
2954             {"single_sample", VK_SAMPLE_COUNT_1_BIT, TEST_SUBTYPE_DEFAULT},
2955             {"msaa_interpolate_at_centroid", VK_SAMPLE_COUNT_4_BIT, TEST_SUBTYPE_MSAA_INTERPOLATE_AT_CENTROID},
2956             {"msaa_interpolate_at_sample", VK_SAMPLE_COUNT_4_BIT, TEST_SUBTYPE_MSAA_INTERPOLATE_AT_SAMPLE},
2957             {"msaa_interpolate_at_offset", VK_SAMPLE_COUNT_4_BIT, TEST_SUBTYPE_MSAA_INTERPOLATE_AT_OFFSET},
2958             {"msaa_centroid_qualifier", VK_SAMPLE_COUNT_4_BIT, TEST_SUBTYPE_MSAA_CENTROID_QUALIFIER},
2959             {"msaa_sample_qualifier", VK_SAMPLE_COUNT_4_BIT, TEST_SUBTYPE_MSAA_SAMPLE_QUALIFIER},
2960         };
2961 
2962         MovePtr<tcu::TestCaseGroup> testTypeGroup(new tcu::TestCaseGroup(testCtx, "weights"));
2963         const TestType testType = TEST_TYPE_WEIGHTS;
2964 
2965         for (size_t provokingVertexNdx = 0; provokingVertexNdx < DE_LENGTH_OF_ARRAY(provokingVertices);
2966              ++provokingVertexNdx)
2967         {
2968             MovePtr<tcu::TestCaseGroup> provokingVertexGroup(
2969                 new tcu::TestCaseGroup(testCtx, provokingVertices[provokingVertexNdx].name, ""));
2970             const bool provokingVertexLast = provokingVertices[provokingVertexNdx].value;
2971 
2972             for (size_t topologyInPipelineNdx = 0; topologyInPipelineNdx < DE_LENGTH_OF_ARRAY(topologiesInPipeline);
2973                  ++topologyInPipelineNdx)
2974             {
2975                 MovePtr<tcu::TestCaseGroup> topologyInPipelineGroup(
2976                     new tcu::TestCaseGroup(testCtx, topologiesInPipeline[topologyInPipelineNdx].name));
2977                 const bool topologyInPipeline = topologiesInPipeline[topologyInPipelineNdx].value;
2978 
2979                 if (topologyInPipeline)
2980                 {
2981                     for (size_t msaaCaseNdx = 0; msaaCaseNdx < DE_LENGTH_OF_ARRAY(msaaCases); ++msaaCaseNdx)
2982                     {
2983                         MovePtr<tcu::TestCaseGroup> msaaGroup(
2984                             new tcu::TestCaseGroup(testCtx, msaaCases[msaaCaseNdx].name));
2985                         for (size_t topologyNdx = 0; topologyNdx < DE_LENGTH_OF_ARRAY(topologies); ++topologyNdx)
2986                         {
2987                             MovePtr<tcu::TestCaseGroup> topologyGroup(
2988                                 new tcu::TestCaseGroup(testCtx, topologies[topologyNdx].name));
2989                             const VkPrimitiveTopology topology = topologies[topologyNdx].topology;
2990                             const bool testableTopology =
2991                                 isPrimitiveTopologyLine(topology) || isPrimitiveTopologyTriangle(topology);
2992 
2993                             if (!testableTopology)
2994                                 continue;
2995 
2996                             for (size_t perspectiveNdx = 0; perspectiveNdx < DE_LENGTH_OF_ARRAY(perspectives);
2997                                  ++perspectiveNdx)
2998                             {
2999                                 MovePtr<tcu::TestCaseGroup> usePerspectiveGroup(
3000                                     new tcu::TestCaseGroup(testCtx, perspectives[perspectiveNdx].name, ""));
3001                                 const bool perspective = perspectives[perspectiveNdx].value;
3002 
3003                                 for (size_t useMeshShaderSpecNdx = 0;
3004                                      useMeshShaderSpecNdx < DE_LENGTH_OF_ARRAY(useMeshShaderSpecs);
3005                                      ++useMeshShaderSpecNdx)
3006                                 {
3007                                     const bool useMeshShader      = useMeshShaderSpecs[useMeshShaderSpecNdx].meshShader;
3008                                     const char *useMeshShaderName = useMeshShaderSpecs[useMeshShaderSpecNdx].name;
3009 
3010                                     if (useMeshShader && !(topology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST ||
3011                                                            topology == VK_PRIMITIVE_TOPOLOGY_LINE_LIST ||
3012                                                            topology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST))
3013                                         // mesh shader support only for point, line or triangle list topology
3014                                         continue;
3015 
3016                                     if (useMeshShader && topologyInPipeline)
3017                                     {
3018                                         // topology is a dynamic state, so cannot use mesh shaders
3019                                         // """
3020                                         //  If the pipeline requires pre - rasterization shader state, and includes a mesh shader,
3021                                         //  there must be no element of the pDynamicStates member of pDynamicState set to VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY,
3022                                         //  or VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE
3023                                         // """
3024                                         continue;
3025                                     }
3026 
3027                                     const TestParams testParams{
3028                                         constructionTypeCase.constructionType,
3029                                         testType,                       //  TestType testType;
3030                                         msaaCases[msaaCaseNdx].subtype, //  TestSubtype testSubtype;
3031                                         topology,                       //  VkPrimitiveTopology topology;
3032                                         notused,                        //  bool dynamicIndexing;
3033                                         (size_t)notused,                //  size_t aggregate;
3034                                         (glu::DataType)notused,         //  glu::DataType dataType;
3035                                         WEIGHT_TEST_WIDTH,              //  uint32_t width;
3036                                         WEIGHT_TEST_HEIGHT,             //  uint32_t height;
3037                                         perspective,                    //  bool perspective;
3038                                         false,                          //  bool provokingVertexLast;
3039                                         0,                              //  uint32_t rotation;
3040                                         topologyInPipeline, //  bool                    dynamicTopologyInPipeline
3041                                         msaaCases[msaaCaseNdx].samples, //  VkSampleCountFlagBits sampleCount;
3042                                         false,         //  bool                    testWithInterpolation
3043                                         false,         //  bool                    testWithFlatInterpolation
3044                                         false,         //  bool                    clipVertices
3045                                         useMeshShader, //    bool                    useMeshShader
3046                                     };
3047 
3048                                     usePerspectiveGroup->addChild(
3049                                         new FragmentShadingBarycentricTestCase(testCtx, useMeshShaderName, testParams));
3050                                 }
3051 
3052                                 topologyGroup->addChild(usePerspectiveGroup.release());
3053                             }
3054                             msaaGroup->addChild(topologyGroup.release());
3055                         }
3056                         topologyInPipelineGroup->addChild(msaaGroup.release());
3057                     }
3058                 }
3059                 else
3060                 {
3061                     for (size_t rotationNdx = 0; rotationNdx < DE_LENGTH_OF_ARRAY(rotations); ++rotationNdx)
3062                     {
3063                         const uint32_t rotation = rotations[rotationNdx];
3064                         MovePtr<tcu::TestCaseGroup> rotationGroup(
3065                             new tcu::TestCaseGroup(testCtx, de::toString(rotation).c_str()));
3066 
3067                         for (size_t topologyNdx = 0; topologyNdx < DE_LENGTH_OF_ARRAY(topologies); ++topologyNdx)
3068                         {
3069                             const VkPrimitiveTopology topology = topologies[topologyNdx].topology;
3070                             MovePtr<tcu::TestCaseGroup> topologyGroup(
3071                                 new tcu::TestCaseGroup(testCtx, topologies[topologyNdx].name));
3072 
3073                             for (size_t perspectiveNdx = 0; perspectiveNdx < DE_LENGTH_OF_ARRAY(perspectives);
3074                                  ++perspectiveNdx)
3075                             {
3076                                 MovePtr<tcu::TestCaseGroup> usePerspectiveGroup(
3077                                     new tcu::TestCaseGroup(testCtx, perspectives[perspectiveNdx].name, ""));
3078                                 const bool perspective = perspectives[perspectiveNdx].value;
3079 
3080                                 for (size_t useMeshShaderSpecNdx = 0;
3081                                      useMeshShaderSpecNdx < DE_LENGTH_OF_ARRAY(useMeshShaderSpecs);
3082                                      ++useMeshShaderSpecNdx)
3083                                 {
3084                                     const bool useMeshShader      = useMeshShaderSpecs[useMeshShaderSpecNdx].meshShader;
3085                                     const char *useMeshShaderName = useMeshShaderSpecs[useMeshShaderSpecNdx].name;
3086 
3087                                     if (useMeshShader && !(topology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST ||
3088                                                            topology == VK_PRIMITIVE_TOPOLOGY_LINE_LIST ||
3089                                                            topology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST))
3090                                     {
3091                                         // mesh shader support only for point, line or triangle list topology
3092                                         continue;
3093                                     }
3094 
3095                                     if (useMeshShader && topologyInPipeline)
3096                                     {
3097                                         // topology is a dynamic state, so cannot use mesh shaders
3098                                         // """
3099                                         //  If the pipeline requires pre - rasterization shader state, and includes a mesh shader,
3100                                         //  there must be no element of the pDynamicStates member of pDynamicState set to VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY,
3101                                         //  or VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE
3102                                         // """
3103                                         continue;
3104                                     }
3105 
3106                                     const TestParams testParams{
3107                                         constructionTypeCase.constructionType,
3108                                         testType,              //  TestType testType;
3109                                         TEST_SUBTYPE_DEFAULT,  //  TestSubtype testSubtype;
3110                                         topology,              //  VkPrimitiveTopology topology;
3111                                         notused,               //  bool dynamicIndexing;
3112                                         (size_t)-1,            //  size_t aggregate;
3113                                         glu::TYPE_INVALID,     //  glu::DataType dataType;
3114                                         WEIGHT_TEST_WIDTH,     //  uint32_t width;
3115                                         WEIGHT_TEST_HEIGHT,    //  uint32_t height;
3116                                         perspective,           //  bool perspective;
3117                                         provokingVertexLast,   //  bool provokingVertexLast;
3118                                         rotation,              //  uint32_t rotation;
3119                                         topologyInPipeline,    //  bool                    dynamicTopologyInPipeline
3120                                         VK_SAMPLE_COUNT_1_BIT, //  VkSampleCountFlagBits sampleCount;
3121                                         false,                 //  bool                    testWithInterpolation
3122                                         false,                 //  bool                    testWithFlatInterpolation
3123                                         false,                 //  bool                    clipVertices
3124                                         useMeshShader,         //    bool                    useMeshShader
3125                                     };
3126 
3127                                     usePerspectiveGroup->addChild(
3128                                         new FragmentShadingBarycentricTestCase(testCtx, useMeshShaderName, testParams));
3129                                 }
3130                                 topologyGroup->addChild(usePerspectiveGroup.release());
3131                             }
3132                             rotationGroup->addChild(topologyGroup.release());
3133                         }
3134 
3135                         topologyInPipelineGroup->addChild(rotationGroup.release());
3136                     }
3137                 }
3138                 provokingVertexGroup->addChild(topologyInPipelineGroup.release());
3139             }
3140             testTypeGroup->addChild(provokingVertexGroup.release());
3141         }
3142 
3143         constructionTypeCase.testGroup->addChild(testTypeGroup.release());
3144     }
3145 
3146     group->addChild(libGroup.release());
3147     group->addChild(fastLinkGroup.release());
3148 
3149     return group.release();
3150 }
3151 
3152 } // namespace FragmentShadingBarycentric
3153 } // namespace vkt
3154