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 "vkDefs.hpp"
27 #include "vktTestCase.hpp"
28 #include "vktTestGroupUtil.hpp"
29 #include "vkCmdUtil.hpp"
30 #include "vkObjUtil.hpp"
31 #include "vkBuilderUtil.hpp"
32 #include "vkBarrierUtil.hpp"
33 #include "vkBufferWithMemory.hpp"
34 #include "vkImageWithMemory.hpp"
35 #include "vkTypeUtil.hpp"
36 #include "vkImageUtil.hpp"
37 #include "vkPipelineConstructionUtil.hpp"
38
39 #include "tcuTestLog.hpp"
40 #include "tcuStringTemplate.hpp"
41 #include "tcuImageCompare.hpp"
42 #include "tcuVectorUtil.hpp"
43
44 #include <string>
45 #include <vector>
46 #include <map>
47
48 namespace vkt
49 {
50 namespace FragmentShadingBarycentric
51 {
52 namespace
53 {
54 using namespace vk;
55 using namespace vkt;
56
57 using std::string;
58 using std::vector;
59 using std::map;
60 using de::MovePtr;
61 using tcu::mix;
62
63 enum TestType
64 {
65 TEST_TYPE_DATA = 0,
66 TEST_TYPE_WEIGHTS,
67 };
68
69 enum TestSubtype
70 {
71 TEST_SUBTYPE_DEFAULT = 0,
72 TEST_SUBTYPE_MSAA_INTERPOLATE_AT_CENTROID,
73 TEST_SUBTYPE_MSAA_INTERPOLATE_AT_SAMPLE,
74 TEST_SUBTYPE_MSAA_INTERPOLATE_AT_OFFSET,
75 TEST_SUBTYPE_MSAA_CENTROID_QUALIFIER,
76 TEST_SUBTYPE_MSAA_SAMPLE_QUALIFIER,
77 TEST_SUBTYPE_PERVERTEX_CORRECTNESS,
78 };
79
80 const size_t DATA_TEST_WIDTH = 8u;
81 const size_t DATA_TEST_HEIGHT = 8u;
82 const size_t WEIGHT_TEST_WIDTH = 128u;
83 const size_t WEIGHT_TEST_HEIGHT = 128u;
84 const float WEIGHT_TEST_SLOPE = 16.0f;
85
86 struct TestParams
87 {
88 const PipelineConstructionType pipelineConstructionType;
89 TestType testType;
90 TestSubtype testSubtype;
91 VkPrimitiveTopology topology;
92 bool dynamicIndexing;
93 size_t aggregate; // 0: value itself, 1:struct, 2+:Array
94 glu::DataType dataType;
95 size_t width;
96 size_t height;
97 bool perspective;
98 bool provokingVertexLast;
99 uint32_t rotation;
100 bool dynamicTopologyInPipeline;
101 VkSampleCountFlagBits sampleCount;
102 };
103
getComponentCount(const TestParams & testParams)104 size_t getComponentCount (const TestParams& testParams)
105 {
106 const size_t scalarSize = static_cast<size_t>(getDataTypeScalarSize(testParams.dataType));
107 const size_t aggregateSize = (testParams.aggregate > 0) ? testParams.aggregate : 1;
108 const size_t topologySize = 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."
109 const size_t result = scalarSize * aggregateSize * topologySize;
110
111 return result;
112 }
113
makeImageCreateInfo(const VkFormat format,const uint32_t width,uint32_t height,VkSampleCountFlagBits samples)114 static VkImageCreateInfo makeImageCreateInfo (const VkFormat format, const uint32_t width, uint32_t height, VkSampleCountFlagBits samples)
115 {
116 const VkImageUsageFlags usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
117 const VkImageCreateInfo imageCreateInfo =
118 {
119 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
120 DE_NULL, // const void* pNext;
121 0u, // VkImageCreateFlags flags;
122 VK_IMAGE_TYPE_2D, // VkImageType imageType;
123 format, // VkFormat format;
124 makeExtent3D(width, height, 1u), // VkExtent3D extent;
125 1u, // uint32_t mipLevels;
126 1u, // uint32_t arrayLayers;
127 samples, // VkSampleCountFlagBits samples;
128 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
129 usage, // VkImageUsageFlags usage;
130 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
131 0u, // uint32_t queueFamilyIndexCount;
132 DE_NULL, // const uint32_t* pQueueFamilyIndices;
133 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
134 };
135
136 return imageCreateInfo;
137 }
138
makeRenderPass(const DeviceInterface & vk,const VkDevice device,const VkFormat format,VkSampleCountFlagBits samples)139 static Move<VkRenderPass> makeRenderPass(const DeviceInterface& vk, const VkDevice device, const VkFormat format, VkSampleCountFlagBits samples)
140 {
141 const VkAttachmentDescription attachmentSingleSampleDesc
142 {
143 (VkAttachmentDescriptionFlags)0u, // VkAttachmentDescriptionFlags flags;
144 format, // VkFormat format;
145 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
146 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
147 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
148 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
149 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
150 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
151 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout;
152 };
153
154 const VkAttachmentDescription attachmentMultiSampleDesc
155 {
156 (VkAttachmentDescriptionFlags)0u, // VkAttachmentDescriptionFlags flags;
157 format, // VkFormat format;
158 samples, // VkSampleCountFlagBits samples;
159 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
160 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
161 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
162 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
163 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
164 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout;
165 };
166
167 const VkAttachmentDescription attachments[] = { attachmentSingleSampleDesc, attachmentMultiSampleDesc };
168
169 const VkAttachmentReference attachmentSingleSampleRef
170 {
171 0u, // deUint32 attachment;
172 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
173 };
174
175 const VkAttachmentReference attachmentMultiSampleRef
176 {
177 1u, // deUint32 attachment;
178 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
179 };
180
181 const bool useMultisampling = (samples > VK_SAMPLE_COUNT_1_BIT);
182 const VkAttachmentReference* colorAttachment = useMultisampling ? &attachmentMultiSampleRef : &attachmentSingleSampleRef;
183 const VkAttachmentReference* resolveAttachment = useMultisampling ? &attachmentSingleSampleRef : DE_NULL;
184
185 const VkSubpassDescription subpassDescription
186 {
187 (VkSubpassDescriptionFlags)0u, // VkSubpassDescriptionFlags flags;
188 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
189 0u, // deUint32 inputAttachmentCount;
190 DE_NULL, // const VkAttachmentReference* pInputAttachments;
191 1u, // deUint32 colorAttachmentCount;
192 colorAttachment, // const VkAttachmentReference* pColorAttachments;
193 resolveAttachment, // const VkAttachmentReference* pResolveAttachments;
194 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment;
195 0u, // deUint32 preserveAttachmentCount;
196 DE_NULL // const deUint32* pPreserveAttachments;
197 };
198
199 const VkRenderPassCreateInfo renderPassInfo
200 {
201 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
202 DE_NULL, // const void* pNext;
203 (VkRenderPassCreateFlags)0u, // VkRenderPassCreateFlags flags;
204 1u + useMultisampling, // deUint32 attachmentCount;
205 attachments, // const VkAttachmentDescription* pAttachments;
206 1u, // deUint32 subpassCount;
207 &subpassDescription, // const VkSubpassDescription* pSubpasses;
208 0u, // deUint32 dependencyCount;
209 DE_NULL // const VkSubpassDependency* pDependencies;
210 };
211
212 return createRenderPass(vk, device, &renderPassInfo, DE_NULL);
213 }
214
215 using GraphicsPipelinePtr = std::unique_ptr<GraphicsPipelineWrapper>;
216
makeGraphicsPipeline(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)217 static GraphicsPipelinePtr makeGraphicsPipeline (PipelineConstructionType pipelineConstructionType,
218 const InstanceInterface& vki,
219 const DeviceInterface& vkd,
220 const VkPhysicalDevice physicalDevice,
221 const VkDevice device,
222 const std::vector<std::string>& deviceExtensions,
223 const PipelineLayoutWrapper& pipelineLayout,
224 const VkRenderPass renderPass,
225 const ShaderWrapper vertShaderModule,
226 const ShaderWrapper fragShaderModule,
227 const uint32_t width,
228 const uint32_t height,
229 const VkPrimitiveTopology topology,
230 const VkSampleCountFlagBits rasterizationSamples,
231 const bool withColor = false,
232 const bool provokingVertexLast = false,
233 const bool dynamicTopology = false)
234 {
235 const std::vector<VkViewport> viewports (1, makeViewport(width, height));
236 const std::vector<VkRect2D> scissors (1, makeRect2D(width, height));
237 const VkVertexInputBindingDescription vertexInputBindingDescription =
238 {
239 0u, // uint32_t binding;
240 2 * sizeof(tcu::Vec4), // uint32_t stride;
241 VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate;
242 };
243 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] =
244 {
245 {
246 0u, // uint32_t location;
247 0u, // uint32_t binding;
248 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
249 0u // uint32_t offset;
250 },
251 {
252 1u, // uint32_t location;
253 0u, // uint32_t binding;
254 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
255 sizeof(tcu::Vec4) // uint32_t offset;
256 },
257 };
258 const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
259 {
260 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
261 DE_NULL, // const void* pNext;
262 (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags;
263 1u, // uint32_t vertexBindingDescriptionCount;
264 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
265 DE_LENGTH_OF_ARRAY(vertexInputAttributeDescriptions), // uint32_t vertexAttributeDescriptionCount;
266 vertexInputAttributeDescriptions, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
267 };
268 const VkPipelineRasterizationProvokingVertexStateCreateInfoEXT provokingVertexStateCreateInfoEXT =
269 {
270 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_PROVOKING_VERTEX_STATE_CREATE_INFO_EXT, // VkStructureType sType;
271 DE_NULL, // const void* pNext;
272 VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT, // VkProvokingVertexModeEXT provokingVertexMode;
273 };
274 const VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo =
275 {
276 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
277 provokingVertexLast ? &provokingVertexStateCreateInfoEXT : DE_NULL, // const void* pNext;
278 0u, // VkPipelineRasterizationStateCreateFlags flags;
279 VK_FALSE, // VkBool32 depthClampEnable;
280 DE_FALSE, // VkBool32 rasterizerDiscardEnable;
281 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode;
282 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode;
283 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
284 VK_FALSE, // VkBool32 depthBiasEnable;
285 0.0f, // float depthBiasConstantFactor;
286 0.0f, // float depthBiasClamp;
287 0.0f, // float depthBiasSlopeFactor;
288 1.0f // float lineWidth;
289 };
290 const bool isMultiSample = (rasterizationSamples > VK_SAMPLE_COUNT_1_BIT);
291 const VkPipelineMultisampleStateCreateInfo multisampleStateInfo
292 {
293 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
294 nullptr, // const void* pNext;
295 0u, // VkPipelineMultisampleStateCreateFlags flags;
296 rasterizationSamples, // VkSampleCountFlagBits rasterizationSamples;
297 (isMultiSample ? VK_TRUE : VK_FALSE), // VkBool32 sampleShadingEnable;
298 1.0f, // float minSampleShading;
299 DE_NULL, // const VkSampleMask* pSampleMask;
300 VK_FALSE, // VkBool32 alphaToCoverageEnable;
301 VK_FALSE, // VkBool32 alphaToOneEnable;
302 };
303 const VkDynamicState dynamicStates[] =
304 {
305 VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY,
306 };
307 const VkPipelineDynamicStateCreateInfo dynamicStateCreateInfo =
308 {
309 VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType;
310 DE_NULL, // const void* pNext;
311 0u, // VkPipelineDynamicStateCreateFlags flags;
312 DE_LENGTH_OF_ARRAY(dynamicStates), // uint32_t dynamicStateCount;
313 dynamicStates, // const VkDynamicState* pDynamicStates;
314 };
315 const VkPipelineDynamicStateCreateInfo* pDynamicStateCreateInfo = dynamicTopology ? &dynamicStateCreateInfo : DE_NULL;
316 const auto pVertexInputStateCreateInfo = (withColor ? &vertexInputStateInfo : nullptr);
317
318 GraphicsPipelinePtr pipelineWrapperPtr (new GraphicsPipelineWrapper(vki, vkd, physicalDevice, device, deviceExtensions, pipelineConstructionType));
319 auto& pipelineWrapper = *pipelineWrapperPtr.get();
320
321 pipelineWrapper
322 .setMonolithicPipelineLayout(pipelineLayout)
323 .setDefaultDepthStencilState()
324 .setDefaultColorBlendState()
325 .setDefaultTopology(topology)
326 .setDynamicState(pDynamicStateCreateInfo)
327 .setupVertexInputState(pVertexInputStateCreateInfo)
328 .setupPreRasterizationShaderState(viewports, scissors, pipelineLayout, renderPass, 0u, vertShaderModule, &rasterizationStateCreateInfo)
329 .setupFragmentShaderState(pipelineLayout, renderPass, 0u, fragShaderModule)
330 .setupFragmentOutputState(renderPass, 0u, nullptr, &multisampleStateInfo)
331 .buildPipeline();
332
333 return pipelineWrapperPtr;
334 }
335
336 // 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)337 static inline std::string replace(const std::string& str, const std::string& from, const std::string& to)
338 {
339 std::string result(str);
340
341 size_t start_pos = 0;
342 while ((start_pos = result.find(from, start_pos)) != std::string::npos)
343 {
344 result.replace(start_pos, from.length(), to);
345 start_pos += to.length();
346 }
347
348 return result;
349 }
350
351
352 class FragmentShadingBarycentricDataTestInstance : public TestInstance
353 {
354 public:
355 FragmentShadingBarycentricDataTestInstance (Context& context,
356 const TestParams& testParams);
357 virtual ~FragmentShadingBarycentricDataTestInstance ();
358 virtual tcu::TestStatus iterate (void);
359
360 protected:
361 vector<tcu::Vec4> generateVertexBuffer (void);
362 MovePtr<BufferWithMemory> createVertexBuffer (const vector<tcu::Vec4>& vertices);
363 bool verify (BufferWithMemory* resultBuffer);
364 bool getProvokingVertexLast (void);
365
366 TestParams m_testParams;
367 };
368
FragmentShadingBarycentricDataTestInstance(Context & context,const TestParams & testParams)369 FragmentShadingBarycentricDataTestInstance::FragmentShadingBarycentricDataTestInstance (Context& context, const TestParams& testParams)
370 : TestInstance (context)
371 , m_testParams (testParams)
372 {
373 }
374
~FragmentShadingBarycentricDataTestInstance()375 FragmentShadingBarycentricDataTestInstance::~FragmentShadingBarycentricDataTestInstance ()
376 {
377 }
378
generateVertexBuffer(void)379 vector<tcu::Vec4> FragmentShadingBarycentricDataTestInstance::generateVertexBuffer (void)
380 {
381 size_t verticesCount = static_cast<size_t>(~0ull);
382 vector<tcu::Vec4> result;
383
384 switch (m_testParams.topology)
385 {
386 case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
387 {
388 verticesCount = m_testParams.width * m_testParams.height;
389
390 result.reserve(verticesCount);
391
392 for (size_t y = 0; y < m_testParams.height; y++)
393 {
394 const float yy = -1.0f + 2.0f * ((0.5f + float(y)) / float(m_testParams.height));
395
396 for (size_t x = 0; x < m_testParams.width; x++)
397 {
398 const float xx = -1.0f + 2.0f * ((0.5f + float(x)) / float(m_testParams.width));
399
400 result.push_back(tcu::Vec4(xx, yy, 0.0f, 1.0f));
401 }
402 }
403
404 break;
405 }
406
407 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
408 {
409 verticesCount = 2 * m_testParams.height;
410
411 result.reserve(verticesCount);
412
413 for (size_t y = 0; y < m_testParams.height; y++)
414 {
415 const float yy = -1.0f + 2.0f * ((0.5f + float(y)) / float(m_testParams.height));
416
417 result.push_back(tcu::Vec4(-1.0f, yy, 0.0f, 1.0f));
418 result.push_back(tcu::Vec4( 1.0f, yy, 0.0f, 1.0f));
419 }
420
421 break;
422 }
423
424 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
425 {
426 verticesCount = 2 * m_testParams.height;
427
428 result.reserve(verticesCount);
429
430 for (size_t y = 0; y < m_testParams.height; y++)
431 {
432 const float yy = -1.0f + 2.0f * (0.5f + float(y)) / float(m_testParams.height);;
433
434 if (y % 2 == 0)
435 {
436 result.push_back(tcu::Vec4(-2.0f, yy, 0.0f, 1.0f));
437 result.push_back(tcu::Vec4(+2.0f, yy, 0.0f, 1.0f));
438 }
439 else
440 {
441 result.push_back(tcu::Vec4(+2.0f, yy, 0.0f, 1.0f));
442 result.push_back(tcu::Vec4(-2.0f, yy, 0.0f, 1.0f));
443 }
444 }
445
446 break;
447 }
448
449 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
450 {
451 verticesCount = 6;
452
453 result.reserve(verticesCount);
454
455 result.push_back(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
456 result.push_back(tcu::Vec4(-1.0f, +1.0f, 0.0f, 1.0f));
457 result.push_back(tcu::Vec4(+1.0f, +1.0f, 0.0f, 1.0f));
458
459 result.push_back(tcu::Vec4(+1.0f, +1.0f, 0.0f, 1.0f));
460 result.push_back(tcu::Vec4(+1.0f, -1.0f, 0.0f, 1.0f));
461 result.push_back(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
462
463 break;
464 }
465
466 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
467 {
468 verticesCount = 4;
469
470 result.reserve(verticesCount);
471
472 result.push_back(tcu::Vec4(-1.0f, +1.0f, 0.0f, 1.0f));
473 result.push_back(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
474 result.push_back(tcu::Vec4(+1.0f, +1.0f, 0.0f, 1.0f));
475 result.push_back(tcu::Vec4(+1.0f, -1.0f, 0.0f, 1.0f));
476
477 break;
478 }
479
480 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
481 {
482 verticesCount = 4;
483
484 result.reserve(verticesCount);
485
486 result.push_back(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
487 result.push_back(tcu::Vec4(-1.0f, +1.0f, 0.0f, 1.0f));
488 result.push_back(tcu::Vec4(+1.0f, +1.0f, 0.0f, 1.0f));
489 result.push_back(tcu::Vec4(+1.0f, -1.0f, 0.0f, 1.0f));
490
491 break;
492 }
493
494 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
495 {
496 verticesCount = 4 * m_testParams.height;
497
498 result.reserve(verticesCount);
499
500 for (size_t y = 0; y < m_testParams.height; y++)
501 {
502 const float yy = -1.0f + 2.0f * ((0.5f + float(y)) / float(m_testParams.height));
503
504 result.push_back(tcu::Vec4(-2.0f, yy, 0.0f, 1.0f));
505 result.push_back(tcu::Vec4(-1.0f, yy, 0.0f, 1.0f));
506 result.push_back(tcu::Vec4( 1.0f, yy, 0.0f, 1.0f));
507 result.push_back(tcu::Vec4( 2.0f, yy, 0.0f, 1.0f));
508 }
509
510 break;
511 }
512
513 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
514 {
515 verticesCount = 2 * m_testParams.height + 2;
516
517 result.reserve(verticesCount);
518
519 result.push_back(tcu::Vec4(-10.0f, -10.0f, 0.0f, 1.0f));
520
521 for (size_t y = 0; y < m_testParams.height; y++)
522 {
523 const float ky = (0.5f + float(y)) / float(m_testParams.height);
524 const float yy = -1.0f + 2.0f * ky;
525
526 if (y % 2 == 0)
527 {
528 result.push_back(tcu::Vec4(-2.0f, yy, 0.0f, 1.0f));
529 result.push_back(tcu::Vec4(+2.0f, yy, 0.0f, 1.0f));
530 }
531 else
532 {
533 result.push_back(tcu::Vec4(+2.0f, yy, 0.0f, 1.0f));
534 result.push_back(tcu::Vec4(-2.0f, yy, 0.0f, 1.0f));
535 }
536 }
537
538 result.push_back(tcu::Vec4(+10.0f, +10.0f, 0.0f, 1.0f));
539
540 break;
541 }
542
543 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
544 {
545 verticesCount = 12;
546
547 result.reserve(verticesCount);
548
549 result.push_back(tcu::Vec4(-1.0f, +1.0f, 0.0f, 1.0f));
550 result.push_back(tcu::Vec4(+1.0f, +3.0f, 0.0f, 1.0f));
551 result.push_back(tcu::Vec4(+1.0f, +1.0f, 0.0f, 1.0f));
552 result.push_back(tcu::Vec4(+1.0f, -1.0f, 0.0f, 1.0f));
553 result.push_back(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
554 result.push_back(tcu::Vec4(-3.0f, -1.0f, 0.0f, 1.0f));
555
556 result.push_back(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
557 result.push_back(tcu::Vec4(-1.0f, +1.0f, 0.0f, 1.0f));
558 result.push_back(tcu::Vec4(+1.0f, +1.0f, 0.0f, 1.0f));
559 result.push_back(tcu::Vec4(+3.0f, +1.0f, 0.0f, 1.0f));
560 result.push_back(tcu::Vec4(+1.0f, -1.0f, 0.0f, 1.0f));
561 result.push_back(tcu::Vec4(-1.0f, -3.0f, 0.0f, 1.0f));
562
563 break;
564 }
565
566 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
567 {
568 verticesCount = 8;
569
570 result.reserve(verticesCount);
571
572 result.push_back(tcu::Vec4(-1.0f, +1.0f, 0.0f, 1.0f));
573 result.push_back(tcu::Vec4(+1.0f, +3.0f, 0.0f, 1.0f));
574 result.push_back(tcu::Vec4(+1.0f, +1.0f, 0.0f, 1.0f));
575 result.push_back(tcu::Vec4(-3.0f, -1.0f, 0.0f, 1.0f));
576 result.push_back(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
577 result.push_back(tcu::Vec4(+3.0f, +1.0f, 0.0f, 1.0f));
578 result.push_back(tcu::Vec4(+1.0f, -1.0f, 0.0f, 1.0f));
579 result.push_back(tcu::Vec4(-1.0f, -3.0f, 0.0f, 1.0f));
580
581 break;
582 }
583
584 default:
585 TCU_THROW(InternalError, "Unknown topology");
586 }
587
588 DE_ASSERT(result.size() == verticesCount);
589
590 return result;
591 }
592
verify(BufferWithMemory * resultBuffer)593 bool FragmentShadingBarycentricDataTestInstance::verify (BufferWithMemory* resultBuffer)
594 {
595 const size_t components = getComponentCount(m_testParams);
596 const deUint32 expected = m_testParams.testSubtype == TEST_SUBTYPE_PERVERTEX_CORRECTNESS ? 10u : static_cast<deUint32>(1 << components) - 1;
597 const deUint32* retrieved = (deUint32*)resultBuffer->getAllocation().getHostPtr();
598 size_t failures = 0;
599
600 {
601 size_t n = 0;
602
603 for (size_t y = 0; y < m_testParams.height; y++)
604 for (size_t x = 0; x < m_testParams.width; x++)
605 {
606 if (retrieved[n] != expected)
607 failures++;
608
609 n++ ;
610 }
611 }
612
613 if (failures)
614 {
615 const uint8_t places = static_cast<uint8_t>(components / 4);
616 tcu::TestLog& log = m_context.getTestContext().getLog();
617 size_t n = 0;
618 std::ostringstream s;
619
620 s << "Expected mask:" << std::setfill('0') << std::hex << std::setw(places) << expected << std::endl;
621
622 for (size_t y = 0; y < m_testParams.height; y++)
623 {
624 for (size_t x = 0; x < m_testParams.width; x++)
625 {
626 s << std::setw(places) << retrieved[n] << ' ';
627
628 n++;
629 }
630
631 s << std::endl;
632 }
633
634 log << tcu::TestLog::Message << s.str() << tcu::TestLog::EndMessage;
635 }
636
637 return failures == 0;
638 }
639
createVertexBuffer(const vector<tcu::Vec4> & vertices)640 MovePtr<BufferWithMemory> FragmentShadingBarycentricDataTestInstance::createVertexBuffer (const vector<tcu::Vec4>& vertices)
641 {
642 const DeviceInterface& vkd = m_context.getDeviceInterface();
643 const VkDevice device = m_context.getDevice();
644 Allocator& allocator = m_context.getDefaultAllocator();
645 const VkDeviceSize vertexBufferSize = vertices.size() * sizeof(vertices[0]);
646 const VkBufferCreateInfo vertexBufferCreateInfo = makeBufferCreateInfo(vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
647 MovePtr<BufferWithMemory> vertexBuffer = MovePtr<BufferWithMemory>(new BufferWithMemory(vkd, device, allocator, vertexBufferCreateInfo, MemoryRequirement::HostVisible));
648 Allocation& vertexBufferAlloc = vertexBuffer->getAllocation();
649
650 // Initialize vertex data
651 deMemcpy(vertexBufferAlloc.getHostPtr(), vertices.data(), (size_t)vertexBufferSize);
652 flushAlloc(vkd, device, vertexBufferAlloc);
653
654 return vertexBuffer;
655 }
656
getProvokingVertexLast(void)657 bool FragmentShadingBarycentricDataTestInstance::getProvokingVertexLast (void)
658 {
659 if (m_testParams.provokingVertexLast && m_testParams.topology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP)
660 {
661 const VkPhysicalDeviceFragmentShaderBarycentricPropertiesKHR& fragmentShaderBarycentricProperties = m_context.getFragmentShaderBarycentricProperties();
662
663 if (fragmentShaderBarycentricProperties.triStripVertexOrderIndependentOfProvokingVertex)
664 return false;
665 }
666
667 return m_testParams.provokingVertexLast;
668 }
669
iterate(void)670 tcu::TestStatus FragmentShadingBarycentricDataTestInstance::iterate (void)
671 {
672 const InstanceInterface& vki = m_context.getInstanceInterface();
673 const DeviceInterface& vkd = m_context.getDeviceInterface();
674 const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
675 const VkDevice device = m_context.getDevice();
676 const auto& deviceExtensions = m_context.getDeviceExtensions();
677 const VkQueue queue = m_context.getUniversalQueue();
678 Allocator& allocator = m_context.getDefaultAllocator();
679 const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
680
681 const VkDeviceSize offsetZero = 0ull;
682 const VkFormat format = VK_FORMAT_R32_UINT;
683 const uint32_t pixelSize = mapVkFormat(format).getPixelSize();
684 const tcu::Vec4 clearColor = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
685 const uint32_t width = static_cast<deUint32>(m_testParams.width);
686 const uint32_t height = static_cast<deUint32>(m_testParams.height);
687 const VkPrimitiveTopology topology = m_testParams.topology;
688 const bool withColor = false;
689 const bool provokingVertexLast = getProvokingVertexLast();
690
691 const vector<tcu::Vec4> vertices = generateVertexBuffer();
692 const uint32_t vertexCount = static_cast<uint32_t>(vertices.size());
693 MovePtr<BufferWithMemory> vertexBuffer = createVertexBuffer(vertices);
694
695 const VkImageCreateInfo imageCreateInfo = makeImageCreateInfo(format, width, height, VK_SAMPLE_COUNT_1_BIT);
696 const VkImageSubresourceRange imageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
697 const MovePtr<ImageWithMemory> image = MovePtr<ImageWithMemory>(new ImageWithMemory(vkd, device, allocator, imageCreateInfo, MemoryRequirement::Any));
698 const Move<VkImageView> imageView = makeImageView(vkd, device, **image, VK_IMAGE_VIEW_TYPE_2D, format, imageSubresourceRange);
699
700 const VkBufferCreateInfo resultBufferCreateInfo = makeBufferCreateInfo(width * height * pixelSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
701 MovePtr<BufferWithMemory> resultBuffer = MovePtr<BufferWithMemory>(new BufferWithMemory(vkd, device, allocator, resultBufferCreateInfo, MemoryRequirement::HostVisible));
702
703 const string shaderSuffix = (provokingVertexLast == m_testParams.provokingVertexLast) ? "" : "-forced";
704 const ShaderWrapper vertModule = ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("vert" + shaderSuffix), 0u);
705 const ShaderWrapper fragModule = ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("frag" + shaderSuffix), 0u);
706 RenderPassWrapper renderPass = RenderPassWrapper(m_testParams.pipelineConstructionType, vkd, device, format);
707 renderPass.createFramebuffer(vkd, device, **image, *imageView, width, height);
708 const deUint32 pushConstants[] = { 0, 1, 2 };
709 const VkPushConstantRange pushConstantRange = makePushConstantRange(VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(pushConstants));
710 const VkPushConstantRange* pushConstantRangePtr = m_testParams.dynamicIndexing ? &pushConstantRange : DE_NULL;
711 const deUint32 pushConstantRangeCount = m_testParams.dynamicIndexing ? 1 : 0;
712 const PipelineLayoutWrapper pipelineLayout (m_testParams.pipelineConstructionType, vkd, device, 0, DE_NULL, pushConstantRangeCount, pushConstantRangePtr);
713 const auto pipelineWrapper = makeGraphicsPipeline(m_testParams.pipelineConstructionType, vki, vkd, physicalDevice, device, deviceExtensions, pipelineLayout, *renderPass, vertModule, fragModule, width, height, topology, VK_SAMPLE_COUNT_1_BIT, withColor, provokingVertexLast);
714
715 const Move<VkCommandPool> commandPool = createCommandPool(vkd, device, 0, queueFamilyIndex);
716 const Move<VkCommandBuffer> commandBuffer = allocateCommandBuffer(vkd, device, *commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
717
718 beginCommandBuffer(vkd, *commandBuffer);
719 {
720 renderPass.begin(vkd, *commandBuffer, makeRect2D(width, height), clearColor);
721
722 pipelineWrapper->bind(*commandBuffer);
723
724 vkd.cmdBindVertexBuffers(*commandBuffer, 0u, 1u, &vertexBuffer->get(), &offsetZero);
725
726 if (m_testParams.dynamicIndexing)
727 vkd.cmdPushConstants(*commandBuffer, *pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0u, sizeof(pushConstants), &pushConstants);
728
729 vkd.cmdDraw(*commandBuffer, vertexCount, 1u, 0u, 0u);
730
731 renderPass.end(vkd, *commandBuffer);
732
733 copyImageToBuffer(vkd, *commandBuffer, image->get(), resultBuffer->get(), tcu::IVec2(width, height));
734 }
735
736 endCommandBuffer(vkd, *commandBuffer);
737 submitCommandsAndWait(vkd, device, queue, *commandBuffer);
738
739 invalidateMappedMemoryRange(vkd, device, resultBuffer->getAllocation().getMemory(), resultBuffer->getAllocation().getOffset(), VK_WHOLE_SIZE);
740
741 DE_ASSERT(8 * pixelSize >= getComponentCount(m_testParams));
742
743 if (verify(resultBuffer.get()))
744 return tcu::TestStatus::pass("Pass");
745 else
746 return tcu::TestStatus::fail("Fail");
747 }
748
749
750 class FragmentShadingBarycentricWeightTestInstance : public TestInstance
751 {
752 public:
753 FragmentShadingBarycentricWeightTestInstance (Context& context,
754 const TestParams& testParams);
755 virtual ~FragmentShadingBarycentricWeightTestInstance ();
756 virtual tcu::TestStatus iterate (void);
757
758 protected:
759 void addVertexWithColor (vector<tcu::Vec4>& vertices,
760 const tcu::Vec4& vertex,
761 const tcu::Vec4& color);
762 vector<tcu::Vec4> generateVertexBuffer (void);
763 MovePtr<BufferWithMemory> createVertexBuffer (const vector<tcu::Vec4>& vertices);
764 bool verify (VkFormat format,
765 BufferWithMemory* referenceBuffer,
766 BufferWithMemory* resultBuffer);
767
768 TestParams m_testParams;
769 };
770
FragmentShadingBarycentricWeightTestInstance(Context & context,const TestParams & testParams)771 FragmentShadingBarycentricWeightTestInstance::FragmentShadingBarycentricWeightTestInstance (Context& context, const TestParams& testParams)
772 : TestInstance (context)
773 , m_testParams (testParams)
774 {
775 }
776
~FragmentShadingBarycentricWeightTestInstance()777 FragmentShadingBarycentricWeightTestInstance::~FragmentShadingBarycentricWeightTestInstance ()
778 {
779 }
780
addVertexWithColor(vector<tcu::Vec4> & vertices,const tcu::Vec4 & vertex,const tcu::Vec4 & color)781 void FragmentShadingBarycentricWeightTestInstance::addVertexWithColor (vector<tcu::Vec4>& vertices,
782 const tcu::Vec4& vertex,
783 const tcu::Vec4& color)
784 {
785 vertices.push_back(vertex);
786 vertices.push_back(color);
787 }
788
generateVertexBuffer(void)789 vector<tcu::Vec4> FragmentShadingBarycentricWeightTestInstance::generateVertexBuffer (void)
790 {
791 const float slope = WEIGHT_TEST_SLOPE;
792 const tcu::Vec4 leftBotColor = tcu::Vec4(0.00f, 0.00f, 0.00f, 1.0f);
793 const tcu::Vec4 leftTopColor = tcu::Vec4(1.00f, 0.00f, 0.00f, 1.0f);
794 const tcu::Vec4 rightTopColor = tcu::Vec4(0.00f, 1.00f, 0.00f, 1.0f);
795 const tcu::Vec4 rightBotColor = tcu::Vec4(0.00f, 0.00f, 1.00f, 1.0f);
796 const tcu::Vec4 noneColor = tcu::Vec4(0.25f, 0.50f, 0.75f, 1.0f);
797 size_t vertexCount = static_cast<size_t>(~0ull);
798 vector<tcu::Vec4> result;
799
800 DE_ASSERT(slope >= 1.0f);
801
802 switch (m_testParams.topology)
803 {
804 case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
805 {
806 vertexCount = m_testParams.width * m_testParams.height;
807
808 result.reserve(2 * vertexCount);
809
810 for (size_t y = 0; y < m_testParams.height; y++)
811 {
812 const float ky = (0.5f + float(y)) / float(m_testParams.height);
813 const float yy = -1.0f + 2.0f * ky;
814 const tcu::Vec4 leftColor = mix(leftTopColor, leftBotColor, ky);
815 const tcu::Vec4 rightColor = mix(rightTopColor, rightBotColor, ky);
816
817 for (size_t x = 0; x < m_testParams.width; x++)
818 {
819 const float kx = (0.5f + float(x)) / float(m_testParams.width);
820 const float xx = -1.0f + 2.0f * kx;
821 const float pointSlope = 1.0f + kx * (slope - 1.0f);
822 const tcu::Vec4 point = tcu::Vec4(xx, yy, 0.0f, 1.0f) * pointSlope;
823 const tcu::Vec4 color = mix(leftColor, rightColor, kx);
824
825 addVertexWithColor(result, point, color);
826 }
827 }
828
829 break;
830 }
831
832 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
833 {
834 vertexCount = 2 * m_testParams.height;
835
836 result.reserve(2 * vertexCount);
837
838 for (size_t y = 0; y < m_testParams.height; y++)
839 {
840 const float ky = (0.5f + float(y)) / float(m_testParams.height);
841 const float yy = -1.0f + 2.0f * ky;
842 const tcu::Vec4 leftColor = mix(leftTopColor, leftBotColor, ky);
843 const tcu::Vec4 rightColor = mix(rightTopColor, rightBotColor, ky);
844 const tcu::Vec4 left = tcu::Vec4(-1.0f, yy, 0.0f, 1.0f);
845 const tcu::Vec4 right = tcu::Vec4( 1.0f, yy, 0.0f, 1.0f) * slope;
846
847 addVertexWithColor(result, left, leftColor);
848 addVertexWithColor(result, right, rightColor);
849 }
850
851 break;
852 }
853
854 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
855 {
856 vertexCount = 2 * m_testParams.height;
857
858 result.reserve(2 * vertexCount);
859
860 for (size_t y = 0; y < m_testParams.height; y++)
861 {
862 const float ky = (0.5f + float(y)) / float(m_testParams.height);
863 const float yy = -1.0f + 2.0f * ky;
864 const tcu::Vec4 leftColor = mix(leftTopColor, leftBotColor, ky);
865 const tcu::Vec4 rightColor = mix(rightTopColor, rightBotColor, ky);
866 const tcu::Vec4 left = tcu::Vec4(-2.0f, yy, 0.0f, 1.0f);
867 const tcu::Vec4 right = tcu::Vec4( 2.0f, yy, 0.0f, 1.0f) * slope;
868
869 if (y % 2 == 0)
870 {
871 addVertexWithColor(result, left, leftColor);
872 addVertexWithColor(result, right, rightColor);
873 }
874 else
875 {
876 addVertexWithColor(result, right, rightColor);
877 addVertexWithColor(result, left, leftColor);
878 }
879 }
880
881 break;
882 }
883
884 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
885 {
886 vertexCount = 6;
887
888 result.reserve(2 * vertexCount);
889
890 addVertexWithColor(result, tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), leftTopColor);
891 addVertexWithColor(result, tcu::Vec4(-1.0f, +1.0f, 0.0f, 1.0f), leftBotColor);
892 addVertexWithColor(result, tcu::Vec4(+1.0f, +1.0f, 0.0f, 1.0f) * slope, rightBotColor);
893
894 addVertexWithColor(result, tcu::Vec4(+1.0f, +1.0f, 0.0f, 1.0f) * slope, rightBotColor);
895 addVertexWithColor(result, tcu::Vec4(+1.0f, -1.0f, 0.0f, 1.0f) * slope, rightTopColor);
896 addVertexWithColor(result, tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), leftTopColor);
897
898 break;
899 }
900
901 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
902 {
903 vertexCount = 4;
904
905 result.reserve(2 * vertexCount);
906
907 addVertexWithColor(result, tcu::Vec4(-1.0f, +1.0f, 0.0f, 1.0f), leftBotColor);
908 addVertexWithColor(result, tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), leftTopColor);
909 addVertexWithColor(result, tcu::Vec4(+1.0f, +1.0f, 0.0f, 1.0f) * slope, rightBotColor);
910 addVertexWithColor(result, tcu::Vec4(+1.0f, -1.0f, 0.0f, 1.0f) * slope, rightTopColor);
911
912 break;
913 }
914
915 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
916 {
917 vertexCount = 4;
918
919 result.reserve(2 * vertexCount);
920
921 addVertexWithColor(result, tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), leftTopColor);
922 addVertexWithColor(result, tcu::Vec4(-1.0f, +1.0f, 0.0f, 1.0f), leftBotColor);
923 addVertexWithColor(result, tcu::Vec4(+1.0f, +1.0f, 0.0f, 1.0f) * slope, rightBotColor);
924 addVertexWithColor(result, tcu::Vec4(+1.0f, -1.0f, 0.0f, 1.0f) * slope, rightTopColor);
925
926 break;
927 }
928
929 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
930 {
931 vertexCount = 4 * m_testParams.height;
932
933 result.reserve(2 * vertexCount);
934
935 for (size_t y = 0; y < m_testParams.height; y++)
936 {
937 const float ky = (0.5f + float(y)) / float(m_testParams.height);
938 const float yy = -1.0f + 2.0f * ky;
939 const tcu::Vec4 leftColor = mix(leftTopColor, leftBotColor, ky);
940 const tcu::Vec4 rightColor = mix(rightTopColor, rightBotColor, ky);
941 const tcu::Vec4 preLeft = tcu::Vec4(-2.0f, yy, 0.0f, 1.0f);
942 const tcu::Vec4 left = tcu::Vec4(-1.0f, yy, 0.0f, 1.0f);
943 const tcu::Vec4 right = tcu::Vec4( 1.0f, yy, 0.0f, 1.0f) * slope;
944 const tcu::Vec4 afterRight = tcu::Vec4( 2.0f, yy, 0.0f, 1.0f) * slope;
945
946 addVertexWithColor(result, preLeft, noneColor);
947 addVertexWithColor(result, left, leftColor);
948 addVertexWithColor(result, right, rightColor);
949 addVertexWithColor(result, afterRight, noneColor);
950 }
951
952 break;
953 }
954
955 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
956 {
957 vertexCount = 2 * m_testParams.height + 2;
958
959 result.reserve(2 * vertexCount);
960
961 addVertexWithColor(result, tcu::Vec4(-10.0f, -10.0f, 0.0f, 1.0f), noneColor);
962
963 for (size_t y = 0; y < m_testParams.height; y++)
964 {
965 const float ky = (0.5f + float(y)) / float(m_testParams.height);
966 const float yy = -1.0f + 2.0f * ky;
967 const tcu::Vec4 leftColor = mix(leftTopColor, leftBotColor, ky);
968 const tcu::Vec4 rightColor = mix(rightTopColor, rightBotColor, ky);
969 const tcu::Vec4 left = tcu::Vec4(-2.0f, yy, 0.0f, 1.0f);
970 const tcu::Vec4 right = tcu::Vec4( 2.0f, yy, 0.0f, 1.0f) * slope;
971
972 if (y % 2 == 0)
973 {
974 addVertexWithColor(result, left, leftColor);
975 addVertexWithColor(result, right, rightColor);
976 }
977 else
978 {
979 addVertexWithColor(result, right, rightColor);
980 addVertexWithColor(result, left, leftColor);
981 }
982 }
983
984 addVertexWithColor(result, tcu::Vec4(+10.0f, +10.0f, 0.0f, 1.0f), noneColor);
985
986 break;
987 }
988
989 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
990 {
991 vertexCount = 12;
992
993 result.reserve(2 * vertexCount);
994
995 addVertexWithColor(result, tcu::Vec4(-1.0f, +1.0f, 0.0f, 1.0f), leftBotColor);
996 addVertexWithColor(result, tcu::Vec4(-3.0f, +1.0f, 0.0f, 1.0f), noneColor);
997 addVertexWithColor(result, tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), leftTopColor);
998 addVertexWithColor(result, tcu::Vec4(+1.0f, -1.0f, 0.0f, 1.0f) * slope, noneColor);
999 addVertexWithColor(result, tcu::Vec4(+1.0f, +1.0f, 0.0f, 1.0f) * slope, rightBotColor);
1000 addVertexWithColor(result, tcu::Vec4(+1.0f, +3.0f, 0.0f, 1.0f) * slope, noneColor);
1001
1002 addVertexWithColor(result, tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), leftTopColor);
1003 addVertexWithColor(result, tcu::Vec4(-1.0f, +1.0f, 0.0f, 1.0f), noneColor);
1004 addVertexWithColor(result, tcu::Vec4(+1.0f, +1.0f, 0.0f, 1.0f) * slope, rightBotColor);
1005 addVertexWithColor(result, tcu::Vec4(+3.0f, +1.0f, 0.0f, 1.0f) * slope, noneColor);
1006 addVertexWithColor(result, tcu::Vec4(+1.0f, -1.0f, 0.0f, 1.0f) * slope, rightTopColor);
1007 addVertexWithColor(result, tcu::Vec4(-1.0f, -3.0f, 0.0f, 1.0f), leftTopColor);
1008
1009 break;
1010 }
1011
1012 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
1013 {
1014 vertexCount = 8;
1015
1016 result.reserve(2 * vertexCount);
1017
1018 addVertexWithColor(result, tcu::Vec4(-1.0f, +1.0f, 0.0f, 1.0f), leftBotColor);
1019 addVertexWithColor(result, tcu::Vec4(-3.0f, -1.0f, 0.0f, 1.0f), noneColor);
1020 addVertexWithColor(result, tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), leftTopColor);
1021 addVertexWithColor(result, tcu::Vec4(+1.0f, +3.0f, 0.0f, 1.0f) * slope, noneColor);
1022 addVertexWithColor(result, tcu::Vec4(+1.0f, +1.0f, 0.0f, 1.0f) * slope, rightBotColor);
1023 addVertexWithColor(result, tcu::Vec4(-1.0f, -3.0f, 0.0f, 1.0f), noneColor);
1024 addVertexWithColor(result, tcu::Vec4(+1.0f, -1.0f, 0.0f, 1.0f) * slope, rightTopColor);
1025 addVertexWithColor(result, tcu::Vec4(+1.0f, +3.0f, 0.0f, 1.0f) * slope, noneColor);
1026
1027 break;
1028 }
1029
1030 default:
1031 TCU_THROW(InternalError, "Unknown topology");
1032 }
1033
1034 DE_ASSERT(result.size() == 2 * vertexCount);
1035
1036 return result;
1037 }
1038
verify(VkFormat format,BufferWithMemory * referenceBuffer,BufferWithMemory * resultBuffer)1039 bool FragmentShadingBarycentricWeightTestInstance::verify (VkFormat format, BufferWithMemory* referenceBuffer, BufferWithMemory* resultBuffer)
1040 {
1041 const deUint32* refernceData = (deUint32*)referenceBuffer->getAllocation().getHostPtr();
1042 const deUint32* resultData = (deUint32*)resultBuffer->getAllocation().getHostPtr();
1043 tcu::TestLog& log = m_context.getTestContext().getLog();
1044 const tcu::ConstPixelBufferAccess refImage (mapVkFormat(format), (int)m_testParams.width, (int)m_testParams.height, 1u, refernceData);
1045 const tcu::ConstPixelBufferAccess resultImage (mapVkFormat(format), (int)m_testParams.width, (int)m_testParams.height, 1u, resultData);
1046 const tcu::UVec4 threshold (1, 1, 1, 1);
1047 bool result = tcu::intThresholdCompare(log,
1048 "ComparisonResult",
1049 "Image comparison result",
1050 refImage,
1051 resultImage,
1052 threshold,
1053 tcu::COMPARE_LOG_ON_ERROR);
1054
1055 return result;
1056 }
1057
createVertexBuffer(const vector<tcu::Vec4> & vertices)1058 MovePtr<BufferWithMemory> FragmentShadingBarycentricWeightTestInstance::createVertexBuffer (const vector<tcu::Vec4>& vertices)
1059 {
1060 const DeviceInterface& vkd = m_context.getDeviceInterface();
1061 const VkDevice device = m_context.getDevice();
1062 Allocator& allocator = m_context.getDefaultAllocator();
1063 const VkDeviceSize vertexBufferSize = vertices.size() * sizeof(vertices[0]);
1064 const VkBufferCreateInfo vertexBufferCreateInfo = makeBufferCreateInfo(vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
1065 MovePtr<BufferWithMemory> vertexBuffer = MovePtr<BufferWithMemory>(new BufferWithMemory(vkd, device, allocator, vertexBufferCreateInfo, MemoryRequirement::HostVisible));
1066 Allocation& vertexBufferAlloc = vertexBuffer->getAllocation();
1067
1068 // Initialize vertex data
1069 deMemcpy(vertexBufferAlloc.getHostPtr(), vertices.data(), (size_t)vertexBufferSize);
1070 flushAlloc(vkd, device, vertexBufferAlloc);
1071
1072 return vertexBuffer;
1073 }
1074
iterate(void)1075 tcu::TestStatus FragmentShadingBarycentricWeightTestInstance::iterate (void)
1076 {
1077 const InstanceInterface& vki = m_context.getInstanceInterface();
1078 const DeviceInterface& vkd = m_context.getDeviceInterface();
1079 const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
1080 const VkDevice device = m_context.getDevice();
1081 const auto& deviceExtensions = m_context.getDeviceExtensions();
1082 const VkQueue queue = m_context.getUniversalQueue();
1083 Allocator& allocator = m_context.getDefaultAllocator();
1084 const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1085
1086 const VkDeviceSize offsetZero = 0ull;
1087 const VkFormat format = VK_FORMAT_R8G8B8A8_UNORM;
1088 const uint32_t pixelSize = mapVkFormat(format).getPixelSize();
1089 const uint32_t width = static_cast<deUint32>(m_testParams.width);
1090 const uint32_t height = static_cast<deUint32>(m_testParams.height);
1091 const bool dynamicStateTopology = m_testParams.dynamicTopologyInPipeline;
1092 const VkPrimitiveTopology pipelineTopology = dynamicStateTopology ? primitiveTopologyCastToList(m_testParams.topology) : m_testParams.topology;
1093 const bool withColor = true;
1094 const bool provokingVertexLast = m_testParams.provokingVertexLast;
1095 const bool useMultisampling = m_testParams.sampleCount > VK_SAMPLE_COUNT_1_BIT;
1096 const float teta = deFloatRadians(-float(m_testParams.rotation));
1097 const float mvp[4*4] =
1098 {
1099 cos(teta), -sin(teta), 0.0f, 0.0f,
1100 sin(teta), cos(teta), 0.0f, 0.0f,
1101 0.0f, 0.0f, 1.0f, 0.0f,
1102 0.0f, 0.0f, 0.0f, 1.0f
1103 };
1104 const vector<tcu::Vec4> vertices = generateVertexBuffer();
1105 const uint32_t vertexCount = static_cast<uint32_t>(vertices.size() / 2);
1106 MovePtr<BufferWithMemory> vertexBuffer = createVertexBuffer(vertices);
1107
1108 const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(width * height * pixelSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1109 MovePtr<BufferWithMemory> resultBuffer = MovePtr<BufferWithMemory>(new BufferWithMemory(vkd, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible));
1110 MovePtr<BufferWithMemory> referenceBuffer = MovePtr<BufferWithMemory>(new BufferWithMemory(vkd, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible));
1111 const Move<VkRenderPass> renderPass = makeRenderPass(vkd, device, format, m_testParams.sampleCount);
1112 const Move<VkCommandPool> commandPool = createCommandPool(vkd, device, 0, queueFamilyIndex);
1113 const ShaderWrapper vertModule = ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("vert"), 0u);
1114 const VkImageCreateInfo imageCreateInfo = makeImageCreateInfo(format, width, height, VK_SAMPLE_COUNT_1_BIT);
1115 const VkImageCreateInfo msImageCreateInfo = makeImageCreateInfo(format, width, height, m_testParams.sampleCount);
1116 const VkImageSubresourceRange imageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
1117 const std::vector<VkClearValue> clearValues (2u, makeClearValueColorU32(0u, 0u, 0u, 0u));
1118
1119 std::vector<VkImageMemoryBarrier> initialImageBarriers(2, makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, DE_NULL, imageSubresourceRange));
1120
1121 for (size_t ndx = 0; ndx < 2; ndx++)
1122 {
1123 const MovePtr<ImageWithMemory> image = MovePtr<ImageWithMemory>(new ImageWithMemory(vkd, device, allocator, imageCreateInfo, MemoryRequirement::Any));
1124 const Move<VkImageView> imageView = makeImageView(vkd, device, **image, VK_IMAGE_VIEW_TYPE_2D, format, imageSubresourceRange);
1125 MovePtr<ImageWithMemory> msImage;
1126 Move<VkImageView> msImageView;
1127
1128 initialImageBarriers[0].image = **image;
1129
1130 if (useMultisampling)
1131 {
1132 msImage = MovePtr<ImageWithMemory>(new ImageWithMemory(vkd, device, allocator, msImageCreateInfo, MemoryRequirement::Any));
1133 msImageView = makeImageView(vkd, device, **msImage, VK_IMAGE_VIEW_TYPE_2D, format, imageSubresourceRange);
1134 initialImageBarriers[1].image = **msImage;
1135 }
1136
1137 const std::vector<VkImageView> imageViewVect = { *imageView, *msImageView };
1138 const Move<VkFramebuffer> framebuffer = makeFramebuffer(vkd, device, *renderPass, 1u + useMultisampling, imageViewVect.data(), width, height);
1139 const Move<VkCommandBuffer> commandBuffer = allocateCommandBuffer(vkd, device, *commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1140 const BufferWithMemory* buffer = (ndx == 0) ? resultBuffer.get() : referenceBuffer.get();
1141 const string fragModuleName = (ndx == 0) ? "frag_test" : "frag_reference";
1142 const ShaderWrapper fragModule = ShaderWrapper(vkd, device, m_context.getBinaryCollection().get(fragModuleName), 0u);
1143 const VkPushConstantRange pushConstantRange = makePushConstantRange(VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(mvp));
1144 const PipelineLayoutWrapper pipelineLayout (m_testParams.pipelineConstructionType, vkd, device, 0, DE_NULL, 1, &pushConstantRange);
1145 const auto pipelineWrapper = makeGraphicsPipeline(m_testParams.pipelineConstructionType, vki, vkd, physicalDevice, device, deviceExtensions, pipelineLayout, *renderPass, vertModule, fragModule, width, height, pipelineTopology, m_testParams.sampleCount, withColor, provokingVertexLast, dynamicStateTopology);
1146 const VkPipeline pipeline = pipelineWrapper->getPipeline();
1147
1148 beginCommandBuffer(vkd, *commandBuffer);
1149 {
1150 cmdPipelineImageMemoryBarrier(vkd, *commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, initialImageBarriers.data(), 1u + useMultisampling);
1151
1152 if (dynamicStateTopology)
1153 vkd.cmdSetPrimitiveTopology(*commandBuffer, m_testParams.topology);
1154
1155 beginRenderPass(vkd, *commandBuffer, *renderPass, *framebuffer, makeRect2D(width, height), 1u + useMultisampling, clearValues.data());
1156 {
1157 vkd.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
1158
1159 vkd.cmdBindVertexBuffers(*commandBuffer, 0u, 1u, &vertexBuffer->get(), &offsetZero);
1160
1161 vkd.cmdPushConstants(*commandBuffer, *pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0u, sizeof(mvp), &mvp);
1162
1163 vkd.cmdDraw(*commandBuffer, vertexCount, 1u, 0u, 0u);
1164 }
1165 endRenderPass(vkd, *commandBuffer);
1166
1167 copyImageToBuffer(vkd, *commandBuffer, image->get(), buffer->get(), tcu::IVec2(width, height));
1168 }
1169 endCommandBuffer(vkd, *commandBuffer);
1170 submitCommandsAndWait(vkd, device, queue, *commandBuffer);
1171
1172 invalidateMappedMemoryRange(vkd, device, buffer->getAllocation().getMemory(), buffer->getAllocation().getOffset(), VK_WHOLE_SIZE);
1173 }
1174
1175 if (verify(format, referenceBuffer.get(), resultBuffer.get()))
1176 return tcu::TestStatus::pass("Pass");
1177 else
1178 return tcu::TestStatus::fail("Fail");
1179 }
1180
1181
1182 class FragmentShadingBarycentricTestCase : public TestCase
1183 {
1184 public:
1185 FragmentShadingBarycentricTestCase (tcu::TestContext& context,
1186 const char* name,
1187 const TestParams testParams);
1188 ~FragmentShadingBarycentricTestCase (void);
1189
1190 virtual void checkSupport (Context& context) const;
1191 virtual void initPrograms (SourceCollections& programCollection) const;
1192 virtual TestInstance* createInstance (Context& context) const;
1193
1194 private:
1195 void initDataPrograms (SourceCollections& programCollection) const;
1196 void initMiscDataPrograms (SourceCollections& programCollection) const;
1197 void initWeightPrograms (SourceCollections& programCollection) const;
1198 string getDataPrimitiveFormula (void) const;
1199 string getDataVertexFormula (const uint32_t vertex,
1200 const bool* provokingVertexLastPtr = DE_NULL) const;
1201
1202 TestParams m_testParams;
1203 };
1204
FragmentShadingBarycentricTestCase(tcu::TestContext & context,const char * name,const TestParams testParams)1205 FragmentShadingBarycentricTestCase::FragmentShadingBarycentricTestCase (tcu::TestContext& context, const char* name, const TestParams testParams)
1206 : vkt::TestCase (context, name)
1207 , m_testParams (testParams)
1208 {
1209 }
1210
~FragmentShadingBarycentricTestCase(void)1211 FragmentShadingBarycentricTestCase::~FragmentShadingBarycentricTestCase (void)
1212 {
1213 }
1214
checkSupport(Context & context) const1215 void FragmentShadingBarycentricTestCase::checkSupport (Context& context) const
1216 {
1217 const auto& vki = context.getInstanceInterface();
1218 const auto physicalDevice = context.getPhysicalDevice();
1219
1220 context.requireDeviceFunctionality("VK_KHR_fragment_shader_barycentric");
1221
1222 const VkPhysicalDeviceFragmentShaderBarycentricFeaturesKHR& fragmentShaderBarycentricFeatures = context.getFragmentShaderBarycentricFeatures();
1223
1224 if (!fragmentShaderBarycentricFeatures.fragmentShaderBarycentric)
1225 TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceFragmentShaderBarycentricFeaturesKHR.fragmentShaderBarycentric");
1226
1227 checkPipelineConstructionRequirements(vki, physicalDevice, m_testParams.pipelineConstructionType);
1228
1229 if (m_testParams.provokingVertexLast)
1230 {
1231 context.requireDeviceFunctionality("VK_EXT_provoking_vertex");
1232
1233 const VkPhysicalDeviceProvokingVertexFeaturesEXT& provokingVertexFeaturesEXT = context.getProvokingVertexFeaturesEXT();
1234
1235 if (!provokingVertexFeaturesEXT.provokingVertexLast)
1236 TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceProvokingVertexFeaturesEXT.provokingVertexLast");
1237 }
1238
1239 if (m_testParams.dynamicTopologyInPipeline)
1240 {
1241 context.requireDeviceFunctionality("VK_EXT_extended_dynamic_state");
1242
1243 const VkPhysicalDeviceExtendedDynamicStateFeaturesEXT& extendedDynamicStateFeaturesEXT = context.getExtendedDynamicStateFeaturesEXT();
1244
1245 if (!extendedDynamicStateFeaturesEXT.extendedDynamicState)
1246 TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceExtendedDynamicStateFeaturesEXT.extendedDynamicState");
1247 }
1248
1249 if ((m_testParams.dataType == glu::TYPE_DOUBLE) ||
1250 (m_testParams.dataType == glu::TYPE_DOUBLE_VEC2) ||
1251 (m_testParams.dataType == glu::TYPE_DOUBLE_VEC3) ||
1252 (m_testParams.dataType == glu::TYPE_DOUBLE_VEC4))
1253 {
1254 VkPhysicalDeviceFeatures2 features2;
1255 deMemset(&features2, 0, sizeof(features2));
1256 features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
1257 features2.pNext = nullptr;
1258 vki.getPhysicalDeviceFeatures2(physicalDevice, &features2);
1259 if (features2.features.shaderFloat64 != VK_TRUE)
1260 {
1261 TCU_THROW(NotSupportedError, "shaderFloat64 not supported");
1262 }
1263 }
1264 }
1265
createInstance(Context & context) const1266 TestInstance* FragmentShadingBarycentricTestCase::createInstance (Context& context) const
1267 {
1268 switch (m_testParams.testType)
1269 {
1270 case TEST_TYPE_DATA: return new FragmentShadingBarycentricDataTestInstance(context, m_testParams);
1271 case TEST_TYPE_WEIGHTS: return new FragmentShadingBarycentricWeightTestInstance(context, m_testParams);
1272 default: TCU_THROW(InternalError, "Unknown testType");
1273 }
1274 }
1275
initPrograms(SourceCollections & programCollection) const1276 void FragmentShadingBarycentricTestCase::initPrograms (SourceCollections& programCollection) const
1277 {
1278 switch (m_testParams.testType)
1279 {
1280 case TEST_TYPE_DATA:
1281 if (m_testParams.testSubtype == TEST_SUBTYPE_PERVERTEX_CORRECTNESS)
1282 initMiscDataPrograms(programCollection);
1283 else
1284 initDataPrograms(programCollection);
1285 break;
1286 case TEST_TYPE_WEIGHTS:
1287 initWeightPrograms(programCollection);
1288 break;
1289 default:
1290 TCU_THROW(InternalError, "Unknown testType");
1291 }
1292 }
1293
getDataPrimitiveFormula(void) const1294 string FragmentShadingBarycentricTestCase::getDataPrimitiveFormula (void) const
1295 {
1296 const char* primitiveFormulas[] =
1297 {
1298 "w * y + x", // VK_PRIMITIVE_TOPOLOGY_POINT_LIST
1299 "y", // VK_PRIMITIVE_TOPOLOGY_LINE_LIST
1300 "2*y", // VK_PRIMITIVE_TOPOLOGY_LINE_STRIP
1301 "(x < y) ? 0 : 1", // VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST
1302 "(x < y) ? 0 : 1", // VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP
1303 "(x < y) ? 0 : 1", // VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN
1304 "y", // VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY
1305 "2*y", // VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY
1306 "(x < y) ? 0 : 1", // VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY
1307 "(x < y) ? 0 : 1", // VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY
1308 "NOT IMPLEMENTED", // VK_PRIMITIVE_TOPOLOGY_PATCH_LIST
1309 };
1310
1311 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(primitiveFormulas) == vk::VK_PRIMITIVE_TOPOLOGY_LAST);
1312 DE_ASSERT(m_testParams.topology < DE_LENGTH_OF_ARRAY(primitiveFormulas));
1313
1314 return primitiveFormulas[m_testParams.topology];
1315 }
1316
getDataVertexFormula(const uint32_t vertex,const bool * provokingVertexLastPtr) const1317 string FragmentShadingBarycentricTestCase::getDataVertexFormula (const uint32_t vertex, const bool* provokingVertexLastPtr) const
1318 {
1319 typedef const char* TriVertexFormula[3];
1320
1321 // Accoriding "Barycentric Interpolation" section
1322 const TriVertexFormula topologyVertexFormulas[] =
1323 {
1324 { "p", "p", "p" }, // VK_PRIMITIVE_TOPOLOGY_POINT_LIST
1325 { "2*p", "2*p+1", "2*p+1" }, // VK_PRIMITIVE_TOPOLOGY_LINE_LIST
1326 { "p", "p+1", "p+1" }, // VK_PRIMITIVE_TOPOLOGY_LINE_STRIP
1327 { "3*p", "3*p+1", "3*p+2" }, // VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST
1328 { "p", "even?p+1:p+2", "even?p+2:p+1" }, // VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP
1329 { "p+1", "p+2", "0" }, // VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN
1330 { "4*p+1", "4*p+2", "4*p+2" }, // VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY
1331 { "p+1", "p+2", "p+2" }, // VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY
1332 { "6*p", "6*p+2", "6*p+4" }, // VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY
1333 { "2*p", "even?2*p+2:2*p+4", "even?2*p+4:2*p+2" }, // VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY
1334 { "", "", "" }, // VK_PRIMITIVE_TOPOLOGY_PATCH_LIST
1335 };
1336 const TriVertexFormula topologyVertexFormulasLast[] =
1337 {
1338 { "even?p:p+1", "even?p+1:p", "p+2" }, // VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP
1339 { "0", "p+1", "p+2" }, // VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN
1340 { "even?2*p:2*p+2", "even?2*p+2:2*p", "2*p+4" }, // VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY
1341 };
1342 const bool provokingVertexLast = provokingVertexLastPtr ? (*provokingVertexLastPtr) : m_testParams.provokingVertexLast;
1343 const bool provokingLastTriangleStrip = provokingVertexLast && m_testParams.topology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
1344 const bool provokingLastTriangleFan = provokingVertexLast && m_testParams.topology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN;
1345 const bool provokingLastTriangleStripAdj = provokingVertexLast && m_testParams.topology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY;
1346 const TriVertexFormula* triVertexFormula = provokingLastTriangleStrip ? &topologyVertexFormulasLast[0]
1347 : provokingLastTriangleFan ? &topologyVertexFormulasLast[1]
1348 : provokingLastTriangleStripAdj ? &topologyVertexFormulasLast[2]
1349 : &topologyVertexFormulas[static_cast<size_t>(m_testParams.topology)];
1350
1351 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(topologyVertexFormulas) == vk::VK_PRIMITIVE_TOPOLOGY_LAST);
1352 DE_ASSERT(vertex < DE_LENGTH_OF_ARRAY(triVertexFormula[0]));
1353
1354 return "(" + string(triVertexFormula[0][vertex]) + ")";
1355 }
1356
initDataPrograms(SourceCollections & programCollection) const1357 void FragmentShadingBarycentricTestCase::initDataPrograms (SourceCollections& programCollection) const
1358 {
1359 map<string, string> attributes;
1360 const string primitiveType = string(getDataTypeName(m_testParams.dataType));
1361 const string dataStructType = m_testParams.aggregate == 1 ? "struct DataStruct {" + primitiveType + " q;};" : "";
1362 const string typePrefix = m_testParams.aggregate == 0 ? primitiveType
1363 : m_testParams.aggregate == 1 ? "DataStruct"
1364 : primitiveType;
1365 const string typeSuffix = m_testParams.aggregate == 0 ? ""
1366 : m_testParams.aggregate == 1 ? ""
1367 : "[" + de::toString(m_testParams.aggregate) + "]";
1368 const int scalarSize = getDataTypeScalarSize(m_testParams.dataType);
1369 const string scalarName = getDataTypeName(getDataTypeScalarType(m_testParams.dataType));
1370 const string vectoredInit = (scalarSize == 1) ? primitiveType + "(n)"
1371 : (scalarSize == 2) ? primitiveType + "(" + scalarName + "(n), " + scalarName + "(2*n))"
1372 : (scalarSize == 3) ? primitiveType + "(" + scalarName + "(n), " + scalarName + "(2*n), " + scalarName + "(4*n))"
1373 : (scalarSize == 4) ? primitiveType + "(" + scalarName + "(n), " + scalarName + "(2*n), " + scalarName + "(4*n), " + scalarName + "(8*n))"
1374 : "NOT IMPLEMENTED";
1375 const string value = m_testParams.aggregate == 0 ? vectoredInit
1376 : m_testParams.aggregate == 1 ? "DataStruct(" + vectoredInit + ")"
1377 : m_testParams.aggregate == 2 ? primitiveType + "[2](" + vectoredInit + ", " + scalarName + "(3)*" + vectoredInit + ")"
1378 : "NOT IMPLEMENTED";
1379 const size_t componentCount = getComponentCount(m_testParams);
1380 const string scalarized = (scalarSize == 1) ? "e${R},"
1381 : (scalarSize == 2) ? "e${R}.x,e${R}.y,"
1382 : (scalarSize == 3) ? "e${R}.x,e${R}.y,e${R}.z,"
1383 : (scalarSize == 4) ? "e${R}.x,e${R}.y,e${R}.z,e${R}.w,"
1384 : "NOT IMPLEMENTED";
1385 const string deaggregated = m_testParams.aggregate == 0 ? replace(scalarized, "${R}", "${S}")
1386 : m_testParams.aggregate == 1 ? replace(scalarized, "${R}", "${S}.q")
1387 : m_testParams.aggregate == 2 ? replace(scalarized, "${R}", "${S}[0]") + replace(scalarized, "${R}", "${S}[1]")
1388 : "NOT IMPLEMENTED";
1389 const string unwrap = replace(deaggregated, "${S}", "A") + replace(deaggregated, "${S}", "B")+ replace(deaggregated, "${S}", "C");
1390 const string expected = unwrap.substr(0, unwrap.size() - 1);
1391 const string arrived = replace(expected, "e", "v");
1392 const string dynamicIndexing = m_testParams.dynamicIndexing ? "layout(push_constant) uniform PushConstant { uint n[3]; } pc;\n" : "";
1393 const string i0 = m_testParams.dynamicIndexing ? "pc.n[0]" : "0";
1394 const string i1 = m_testParams.dynamicIndexing ? "pc.n[1]" : "1";
1395 const string i2 = m_testParams.dynamicIndexing ? "pc.n[2]" : "2";
1396 const string primitiveId = getDataPrimitiveFormula();
1397 const string vertexFormula[] = { getDataVertexFormula(0), getDataVertexFormula(1), getDataVertexFormula(2) };
1398 const tcu::StringTemplate vertShader (string(
1399 "#version 450\n"
1400 "#extension GL_EXT_fragment_shader_barycentric : require\n"
1401 "\n"
1402 "${dataStruct}\n"
1403 "\n"
1404 "layout(location = 0) in vec4 in_position;\n"
1405 "layout(location = 0) out ${typePrefix} data${typeSuffix};\n"
1406 "\n"
1407 "out gl_PerVertex\n"
1408 "{\n"
1409 " vec4 gl_Position;\n"
1410 " float gl_PointSize;\n"
1411 "};\n"
1412 "\n"
1413 "void main()\n"
1414 "{\n"
1415 " const int n = gl_VertexIndex + 1;\n"
1416 " data = ${value};\n"
1417 " gl_PointSize = 1.0;\n"
1418 " gl_Position = in_position;\n"
1419 "}\n"));
1420 const tcu::StringTemplate fragShader (
1421 string("#version 450\n") +
1422 "#extension GL_EXT_fragment_shader_barycentric : require\n"
1423 "\n"
1424 "${dataStruct}\n"
1425 "\n"
1426 "${dynamicIndexing}\n"
1427 "layout(location = 0) pervertexEXT in ${typePrefix} data[]${typeSuffix};\n"
1428 "layout(location = 0) out uvec4 out_color;\n"
1429 "\n"
1430 "void main()\n"
1431 "{\n"
1432 " const int w = " + de::toString(m_testParams.width) + ";\n"
1433 " const int h = " + de::toString(m_testParams.height) + ";\n"
1434 " const int x = int(gl_FragCoord.x - 0.5f);\n"
1435 " const int y = int(gl_FragCoord.y - 0.5f);\n"
1436 " const int p = ${primitiveId};\n"
1437 " const bool even = (p%2 == 0);\n"
1438 "\n"
1439 " ${typePrefix} eA${typeSuffix}; { const int n = 1 + ${vertexFormula0}; eA = ${value}; }\n"
1440 " ${typePrefix} eB${typeSuffix}; { const int n = 1 + ${vertexFormula1}; eB = ${value}; }\n"
1441 " ${typePrefix} eC${typeSuffix}; { const int n = 1 + ${vertexFormula2}; eC = ${value}; }\n"
1442 "\n"
1443 " ${scalarName} e[${componentCount}] = { ${expected} };\n"
1444 "\n"
1445 " ${typePrefix} vA${typeSuffix}; { vA = " + string(m_testParams.aggregate == 2 ? "${typePrefix}${typeSuffix}(data[${i0}][0],data[${i0}][1])" : "data[${i0}]") + "; }\n"
1446 " ${typePrefix} vB${typeSuffix}; { vB = " + string(m_testParams.aggregate == 2 ? "${typePrefix}${typeSuffix}(data[${i1}][0],data[${i1}][1])" : "data[${i1}]") + "; }\n"
1447 " ${typePrefix} vC${typeSuffix}; { vC = " + string(m_testParams.aggregate == 2 ? "${typePrefix}${typeSuffix}(data[${i2}][0],data[${i2}][1])" : "data[${i2}]") + "; }\n"
1448 " ${scalarName} v[${componentCount}] = { ${arrived} };\n"
1449 "\n"
1450 " int mask = 0;\n"
1451 "\n"
1452 " for (int i = 0; i<${componentCount}; i++)\n"
1453 " if (e[i] == v[i])\n"
1454 " mask = mask | (1<<i);\n"
1455 "\n"
1456 " out_color = uvec4(mask);\n"
1457 "}\n");
1458
1459 attributes["typePrefix"] = typePrefix;
1460 attributes["typeSuffix"] = typeSuffix;
1461 attributes["value"] = value;
1462 attributes["componentCount"] = de::toString(componentCount);
1463 attributes["expected"] = expected;
1464 attributes["arrived"] = arrived;
1465 attributes["scalarName"] = scalarName;
1466 attributes["dataStruct"] = dataStructType;
1467 attributes["dynamicIndexing"] = dynamicIndexing;
1468 attributes["primitiveId"] = primitiveId;
1469 attributes["i0"] = i0;
1470 attributes["i1"] = i1;
1471 attributes["i2"] = i2;
1472 attributes["vertexFormula0"] = vertexFormula[0];
1473 attributes["vertexFormula1"] = vertexFormula[1];
1474 attributes["vertexFormula2"] = vertexFormula[2];
1475
1476 if (isPrimitiveTopologyLine(m_testParams.topology))
1477 {
1478 DE_ASSERT(vertexFormula[2] == vertexFormula[1]);
1479 }
1480 else if (isPrimitiveTopologyPoint(m_testParams.topology))
1481 {
1482 DE_ASSERT(vertexFormula[2] == vertexFormula[1] && vertexFormula[1] == vertexFormula[0]);
1483 }
1484
1485 programCollection.glslSources.add("vert") << glu::VertexSource(vertShader.specialize(attributes));
1486 programCollection.glslSources.add("frag") << glu::FragmentSource(fragShader.specialize(attributes));
1487
1488 if (m_testParams.provokingVertexLast && m_testParams.topology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP)
1489 {
1490 const bool provokingVertexLast = false;
1491
1492 attributes["vertexFormula0"] = getDataVertexFormula(0, &provokingVertexLast);
1493 attributes["vertexFormula1"] = getDataVertexFormula(1, &provokingVertexLast);
1494 attributes["vertexFormula2"] = getDataVertexFormula(2, &provokingVertexLast);
1495
1496 programCollection.glslSources.add("vert-forced") << glu::VertexSource(vertShader.specialize(attributes));
1497 programCollection.glslSources.add("frag-forced") << glu::FragmentSource(fragShader.specialize(attributes));
1498 }
1499 }
1500
initMiscDataPrograms(SourceCollections & programCollection) const1501 void FragmentShadingBarycentricTestCase::initMiscDataPrograms(SourceCollections& programCollection) const
1502 {
1503 const std::string vertShader(
1504 "#version 450\n"
1505 "#extension GL_EXT_fragment_shader_barycentric : require\n"
1506 "\n"
1507 "layout(location = 0) in vec4 in_position;\n"
1508 "layout(location = 0) out uvec2 dataA;\n"
1509 "layout(location = 1) out uvec2 dataB;\n"
1510 "void main()\n"
1511 "{\n"
1512 // we will draw two triangles and we need to convert dataA for
1513 // second triangle to 0-2 range to simplify verification
1514 " dataA = uvec2(mod(gl_VertexIndex, 3));\n"
1515 " dataB = uvec2(7);\n"
1516 " gl_Position = in_position;\n"
1517 "}\n");
1518 const std::string fragShader(
1519 "#version 450\n"
1520 "#extension GL_EXT_fragment_shader_barycentric : require\n"
1521 "layout(location = 0) pervertexEXT in uvec2 dataA[];\n"
1522 "layout(location = 1) flat in uvec2 dataB;\n"
1523 "layout(location = 0) out uvec4 out_color;\n"
1524 "void main()\n"
1525 "{\n"
1526 // make sure that PerVertex decoration is only applied to location 0
1527 // and that the location 1 isn't compacted/remapped to location 0
1528 // by adding all values and making sure the result is 10
1529 " out_color = uvec4(dataA[0].y + dataA[1].x + dataA[2].y + dataB.x);\n"
1530 "}\n");
1531
1532 programCollection.glslSources.add("vert") << glu::VertexSource(vertShader);
1533 programCollection.glslSources.add("frag") << glu::FragmentSource(fragShader);
1534 }
1535
initWeightPrograms(SourceCollections & programCollection) const1536 void FragmentShadingBarycentricTestCase::initWeightPrograms (SourceCollections& programCollection) const
1537 {
1538 const string baryCoordVariable = m_testParams.perspective
1539 ? "BaryCoord"
1540 : "BaryCoordNoPersp";
1541 const string declspecRef = m_testParams.perspective ? "" : "noperspective";
1542 const string vertShader =
1543 "#version 450\n"
1544 "\n"
1545 "layout(location = 0) in vec4 in_position;\n"
1546 "layout(location = 1) in vec4 in_color;\n"
1547 "layout(location = 0) out vec3 color;\n"
1548 "layout(push_constant) uniform PushConstant { mat4 mvp; } pc;\n"
1549 "\n"
1550 "void main()\n"
1551 "{\n"
1552 " color = in_color.xyz;\n"
1553 " gl_Position = transpose(pc.mvp) * in_position;\n"
1554 " gl_PointSize = 1.0;\n"
1555 "}\n";
1556 const tcu::StringTemplate fragShaderReference(
1557 "#version 450\n"
1558 "\n"
1559 "layout(location = 0) ${glslDeclspecRef} in vec3 in_color;\n"
1560 "layout(location = 0) out vec4 out_color;\n"
1561 "\n"
1562 "void main()\n"
1563 "{\n"
1564 " out_color = vec4(in_color, 1.0f);\n"
1565 "}\n");
1566 const tcu::StringTemplate fragShaderTestGLSL(
1567 "#version 450\n"
1568 "#extension GL_EXT_fragment_shader_barycentric : require\n"
1569 "\n"
1570 "layout(location = 0) pervertexEXT in vec3 in_color[];\n"
1571 "layout(location = 0) out vec4 out_color;\n"
1572 "\n"
1573 "void main()\n"
1574 "{\n"
1575 " vec3 bc = ${glslFormulaeTest};\n"
1576 " out_color = vec4(in_color[0] * bc.x + in_color[1] * bc.y + in_color[2] * bc.z, 1.0f);\n"
1577 "}\n");
1578
1579 // it is not possible to add centroid/sample qualifiers to gl_BaryCoordEXT/gl_BaryCoordNoPerspEXT
1580 // but it is possible to do this with SPIR-V - code below is a slightly modified version of fragShaderTestGLSL
1581 const tcu::StringTemplate fragShaderTestSPIRV(
1582 "OpCapability Shader\n"
1583 "OpCapability FragmentBarycentricKHR\n"
1584 "${spirvAdditionalCapabilities}"
1585 "OpExtension \"SPV_KHR_fragment_shader_barycentric\"\n"
1586 "%1 = OpExtInstImport \"GLSL.std.450\"\n"
1587 "OpMemoryModel Logical GLSL450\n"
1588 "OpEntryPoint Fragment %4 \"main\" %var_BaryCoord %15 %20\n"
1589 "OpExecutionMode %4 OriginUpperLeft\n"
1590 "OpDecorate %var_BaryCoord BuiltIn ${spirvBaryCoordVariable}\n"
1591 "OpDecorate %var_BaryCoord ${spirvBaryCoordDecoration}\n"
1592 "OpDecorate %15 Location 0\n"
1593 "OpDecorate %20 Location 0\n"
1594 "OpDecorate %20 PerVertexKHR\n"
1595 "%2 = OpTypeVoid\n"
1596 "%3 = OpTypeFunction %2\n"
1597 "%6 = OpTypeFloat 32\n"
1598 "%7 = OpTypeVector %6 3\n"
1599 "%8 = OpTypePointer Function %7\n"
1600 "%10 = OpTypePointer Input %7\n"
1601 "%var_BaryCoord = OpVariable %10 Input\n"
1602 "%13 = OpTypeVector %6 4\n"
1603 "%14 = OpTypePointer Output %13\n"
1604 "%15 = OpVariable %14 Output\n"
1605 "%16 = OpTypeInt 32 0\n"
1606 "%17 = OpConstant %16 3\n"
1607 "%18 = OpTypeArray %7 %17\n"
1608 "%19 = OpTypePointer Input %18\n"
1609 "%20 = OpVariable %19 Input\n"
1610 "%21 = OpTypeInt 32 1\n"
1611 "%22 = OpConstant %21 0\n"
1612 "%25 = OpConstant %16 0\n"
1613 "%26 = OpTypePointer Function %6\n"
1614 "%30 = OpConstant %21 1\n"
1615 "%33 = OpConstant %16 1\n"
1616 "%38 = OpConstant %21 2\n"
1617 "%41 = OpConstant %16 2\n"
1618 "%46 = OpConstant %6 1\n"
1619 "%4 = OpFunction %2 None %3\n"
1620 "%5 = OpLabel\n"
1621 "%9 = OpVariable %8 Function\n"
1622 "%12 = OpLoad %7 %var_BaryCoord\n"
1623 "OpStore %9 %12\n"
1624 "%23 = OpAccessChain %10 %20 %22\n"
1625 "%24 = OpLoad %7 %23\n"
1626 "%27 = OpAccessChain %26 %9 %25\n"
1627 "%28 = OpLoad %6 %27\n"
1628 "%29 = OpVectorTimesScalar %7 %24 %28\n"
1629 "%31 = OpAccessChain %10 %20 %30\n"
1630 "%32 = OpLoad %7 %31\n"
1631 "%34 = OpAccessChain %26 %9 %33\n"
1632 "%35 = OpLoad %6 %34\n"
1633 "%36 = OpVectorTimesScalar %7 %32 %35\n"
1634 "%37 = OpFAdd %7 %29 %36\n"
1635 "%39 = OpAccessChain %10 %20 %38\n"
1636 "%40 = OpLoad %7 %39\n"
1637 "%42 = OpAccessChain %26 %9 %41\n"
1638 "%43 = OpLoad %6 %42\n"
1639 "%44 = OpVectorTimesScalar %7 %40 %43\n"
1640 "%45 = OpFAdd %7 %37 %44\n"
1641 "%47 = OpCompositeExtract %6 %45 0\n"
1642 "%48 = OpCompositeExtract %6 %45 1\n"
1643 "%49 = OpCompositeExtract %6 %45 2\n"
1644 "%50 = OpCompositeConstruct %13 %47 %48 %49 %46\n"
1645 "OpStore %15 %50\n"
1646 "OpReturn\n"
1647 "OpFunctionEnd\n");
1648
1649 // use single specialization map for test and reference fragment shaders
1650 // as well as for spirv version of test shader
1651 map<string, string> attributes
1652 {
1653 { "glslDeclspecRef", declspecRef }
1654 };
1655
1656 switch (m_testParams.testSubtype)
1657 {
1658 case TEST_SUBTYPE_MSAA_INTERPOLATE_AT_CENTROID:
1659 attributes["glslFormulaeTest"] = std::string("interpolateAtCentroid(gl_") + baryCoordVariable + "EXT)";
1660 attributes["glslDeclspecRef"] += " centroid";
1661 break;
1662 case TEST_SUBTYPE_MSAA_INTERPOLATE_AT_SAMPLE:
1663 attributes["glslFormulaeTest"] = std::string("interpolateAtSample(gl_") + baryCoordVariable + "EXT, gl_SampleID)";
1664 attributes["glslDeclspecRef"] += " sample";
1665 break;
1666 case TEST_SUBTYPE_MSAA_INTERPOLATE_AT_OFFSET:
1667 attributes["glslFormulaeTest"] = std::string("interpolateAtOffset(gl_") + baryCoordVariable + "EXT, vec2(gl_SamplePosition - vec2(0.5)))";
1668 attributes["glslDeclspecRef"] += " sample";
1669 break;
1670 case TEST_SUBTYPE_MSAA_CENTROID_QUALIFIER:
1671 attributes["spirvBaryCoordVariable"] = baryCoordVariable + "KHR";
1672 attributes["spirvBaryCoordDecoration"] = "Centroid";
1673 attributes["spirvAdditionalCapabilities"] = "";
1674 attributes["glslDeclspecRef"] += " centroid";
1675 break;
1676 case TEST_SUBTYPE_MSAA_SAMPLE_QUALIFIER:
1677 attributes["spirvBaryCoordVariable"] = baryCoordVariable + "KHR";
1678 attributes["spirvBaryCoordDecoration"] = "Sample";
1679 attributes["spirvAdditionalCapabilities"] = "OpCapability SampleRateShading\n";
1680 attributes["glslDeclspecRef"] += " sample";
1681 break;
1682 default:
1683 attributes["glslFormulaeTest"] = std::string("gl_") + baryCoordVariable + "EXT";
1684 break;
1685 }
1686
1687 programCollection.glslSources.add("vert") << glu::VertexSource(vertShader);
1688 programCollection.glslSources.add("frag_reference") << glu::FragmentSource(fragShaderReference.specialize(attributes));
1689
1690 // use "spirvBaryCoordVariable" key to determine if we should use glsl or spir-v version of test shader
1691 if (attributes.count("spirvBaryCoordVariable"))
1692 programCollection.spirvAsmSources.add("frag_test") << fragShaderTestSPIRV.specialize(attributes);
1693 else
1694 programCollection.glslSources.add("frag_test") << glu::FragmentSource(fragShaderTestGLSL.specialize(attributes));
1695 }
1696 } // anonymous
1697
createTests(tcu::TestContext & testCtx,const std::string & name)1698 tcu::TestCaseGroup* createTests (tcu::TestContext& testCtx, const std::string& name)
1699 {
1700 const bool notused = false;
1701 MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, name.c_str(), "Tests fragment shading barycentric extension"));
1702 // Tests using graphics pipeline libraries
1703 MovePtr<tcu::TestCaseGroup> libGroup (new tcu::TestCaseGroup(testCtx, "pipeline_library"));
1704 MovePtr<tcu::TestCaseGroup> fastLinkGroup (new tcu::TestCaseGroup(testCtx, "fast_linked_library", "Tests using graphics pipeline libraries with fast linking"));
1705
1706 const struct
1707 {
1708 PipelineConstructionType constructionType;
1709 tcu::TestCaseGroup* testGroup;
1710 } constructionTypeCases[] =
1711 {
1712 { PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC, group.get() },
1713 { PIPELINE_CONSTRUCTION_TYPE_LINK_TIME_OPTIMIZED_LIBRARY, libGroup.get() },
1714 { PIPELINE_CONSTRUCTION_TYPE_FAST_LINKED_LIBRARY, fastLinkGroup.get() },
1715 };
1716
1717 const struct PrimitiveTestSpec
1718 {
1719 VkPrimitiveTopology topology;
1720 const char* name;
1721 }
1722 topologies[] =
1723 {
1724 { VK_PRIMITIVE_TOPOLOGY_POINT_LIST , "point_list" },
1725 { VK_PRIMITIVE_TOPOLOGY_LINE_LIST , "line_list" },
1726 { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP , "line_strip" },
1727 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST , "triangle_list" },
1728 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP , "triangle_strip" },
1729 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN , "triangle_fan" },
1730 { VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY , "line_list_with_adjacency" },
1731 { VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY , "line_strip_with_adjacency" },
1732 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY , "triangle_list_with_adjacency" },
1733 { VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY , "triangle_strip_with_adjacency" },
1734 };
1735 const glu::DataType dataTypes[] =
1736 {
1737 glu::TYPE_FLOAT,
1738 glu::TYPE_FLOAT_VEC2,
1739 glu::TYPE_FLOAT_VEC3,
1740 glu::TYPE_FLOAT_VEC4,
1741 glu::TYPE_DOUBLE,
1742 glu::TYPE_DOUBLE_VEC2,
1743 glu::TYPE_DOUBLE_VEC3,
1744 glu::TYPE_DOUBLE_VEC4,
1745 glu::TYPE_INT,
1746 glu::TYPE_INT_VEC2,
1747 glu::TYPE_INT_VEC3,
1748 glu::TYPE_INT_VEC4,
1749 glu::TYPE_UINT,
1750 glu::TYPE_UINT_VEC2,
1751 glu::TYPE_UINT_VEC3,
1752 glu::TYPE_UINT_VEC4,
1753 };
1754 const struct Perspective
1755 {
1756 const char* name;
1757 bool value;
1758 }
1759 perspectives[] =
1760 {
1761 { "perspective", true },
1762 { "noperspective", false },
1763 };
1764 const struct DynamicIndexing
1765 {
1766 const char* name;
1767 bool value;
1768 }
1769 dynamicIndexings[] =
1770 {
1771 { "static", false },
1772 { "dynamic", true },
1773 };
1774 const struct ProvokingVertex
1775 {
1776 const char* name;
1777 bool value;
1778 }
1779 provokingVertices[] =
1780 {
1781 { "provoking_first", false },
1782 { "provoking_last", true },
1783 };
1784 const uint32_t rotations[] = { 0, 85, 95 };
1785 const struct TopologyInPipeline
1786 {
1787 const char* name;
1788 bool value;
1789 }
1790 topologiesInPipeline[] =
1791 {
1792 { "pipeline_topology_static", false },
1793 { "pipeline_topology_dynamic", true },
1794 };
1795
1796 for (const auto& constructionTypeCase : constructionTypeCases)
1797 {
1798 MovePtr<tcu::TestCaseGroup> testTypeGroup (new tcu::TestCaseGroup(testCtx, "data"));
1799 const TestType testType = TEST_TYPE_DATA;
1800
1801 for (size_t provokingVertexNdx = 0; provokingVertexNdx < DE_LENGTH_OF_ARRAY(provokingVertices); ++provokingVertexNdx)
1802 {
1803 MovePtr<tcu::TestCaseGroup> provokingVertexGroup (new tcu::TestCaseGroup(testCtx, provokingVertices[provokingVertexNdx].name));
1804 const bool provokingVertexLast = provokingVertices[provokingVertexNdx].value;
1805
1806 for (size_t dynamicNdx = 0; dynamicNdx < DE_LENGTH_OF_ARRAY(dynamicIndexings); ++dynamicNdx)
1807 {
1808 MovePtr<tcu::TestCaseGroup> dynamicIndexingGroup (new tcu::TestCaseGroup(testCtx, dynamicIndexings[dynamicNdx].name));
1809 const bool dynamicIndexing = dynamicIndexings[dynamicNdx].value;
1810
1811 for (size_t topologyNdx = 0; topologyNdx < DE_LENGTH_OF_ARRAY(topologies); ++topologyNdx)
1812 {
1813 MovePtr<tcu::TestCaseGroup> topologyGroup (new tcu::TestCaseGroup(testCtx, topologies[topologyNdx].name));
1814 const VkPrimitiveTopology topology = topologies[topologyNdx].topology;
1815
1816 for (size_t aggregateNdx = 0; aggregateNdx < 3; ++aggregateNdx)
1817 {
1818 const string aggregateName = aggregateNdx == 0 ? "type"
1819 : aggregateNdx == 1 ? "struct"
1820 : "array" + de::toString(aggregateNdx);
1821 MovePtr<tcu::TestCaseGroup> aggregateGroup (new tcu::TestCaseGroup(testCtx, aggregateName.c_str()));
1822
1823 for (size_t dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(dataTypes); ++dataTypeNdx)
1824 {
1825 const glu::DataType dataType = dataTypes[dataTypeNdx];
1826 const char* dataTypeName = getDataTypeName(dataType);
1827
1828 const TestParams testParams
1829 {
1830 constructionTypeCase.constructionType,
1831 testType, // TestType testType;
1832 TEST_SUBTYPE_DEFAULT, // TestSubtype testSubtype;
1833 topology, // VkPrimitiveTopology topology;
1834 dynamicIndexing, // bool dynamicIndexing;
1835 aggregateNdx, // size_t aggregate;
1836 dataType, // glu::DataType dataType;
1837 DATA_TEST_WIDTH, // uint32_t width;
1838 DATA_TEST_HEIGHT, // uint32_t height;
1839 notused, // bool perspective;
1840 provokingVertexLast, // bool provokingVertexLast;
1841 (uint32_t)notused, // uint32_t rotation;
1842 notused, // bool dynamicTopologyInPipeline
1843 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits sampleCount;
1844 };
1845
1846 aggregateGroup->addChild(new FragmentShadingBarycentricTestCase(testCtx, dataTypeName, testParams));
1847 }
1848
1849 topologyGroup->addChild(aggregateGroup.release());
1850 }
1851
1852 dynamicIndexingGroup->addChild(topologyGroup.release());
1853 }
1854
1855 provokingVertexGroup->addChild(dynamicIndexingGroup.release());
1856 }
1857
1858 testTypeGroup->addChild(provokingVertexGroup.release());
1859 }
1860
1861 {
1862 MovePtr<tcu::TestCaseGroup> miscGroup(new tcu::TestCaseGroup(testCtx, "misc"));
1863 const TestParams testParams
1864 {
1865 constructionTypeCase.constructionType,
1866 TEST_TYPE_DATA, // TestType testType;
1867 TEST_SUBTYPE_PERVERTEX_CORRECTNESS, // TestSubtype testSubtype;
1868 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // VkPrimitiveTopology topology;
1869 notused, // bool dynamicIndexing;
1870 notused, // size_t aggregate;
1871 glu::TYPE_FLOAT_VEC2, // glu::DataType dataType;
1872 DATA_TEST_WIDTH, // uint32_t width;
1873 DATA_TEST_HEIGHT, // uint32_t height;
1874 notused, // bool perspective;
1875 notused, // bool provokingVertexLast;
1876 (uint32_t)notused, // uint32_t rotation;
1877 notused, // bool dynamicTopologyInPipeline
1878 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits sampleCount;
1879 };
1880 miscGroup->addChild(new FragmentShadingBarycentricTestCase(testCtx, "pervertex_correctness", testParams));
1881 testTypeGroup->addChild(miscGroup.release());
1882 }
1883
1884 constructionTypeCase.testGroup->addChild(testTypeGroup.release());
1885 }
1886
1887 for (const auto& constructionTypeCase : constructionTypeCases)
1888 {
1889 const struct MsaaTestCase
1890 {
1891 const char* name;
1892 VkSampleCountFlagBits samples;
1893 TestSubtype subtype;
1894 }
1895 msaaCases[] =
1896 {
1897 { "single_sample", VK_SAMPLE_COUNT_1_BIT, TEST_SUBTYPE_DEFAULT },
1898 { "msaa_interpolate_at_centroid", VK_SAMPLE_COUNT_4_BIT, TEST_SUBTYPE_MSAA_INTERPOLATE_AT_CENTROID },
1899 { "msaa_interpolate_at_sample", VK_SAMPLE_COUNT_4_BIT, TEST_SUBTYPE_MSAA_INTERPOLATE_AT_SAMPLE },
1900 { "msaa_interpolate_at_offset", VK_SAMPLE_COUNT_4_BIT, TEST_SUBTYPE_MSAA_INTERPOLATE_AT_OFFSET },
1901 { "msaa_centroid_qualifier", VK_SAMPLE_COUNT_4_BIT, TEST_SUBTYPE_MSAA_CENTROID_QUALIFIER },
1902 { "msaa_sample_qualifier", VK_SAMPLE_COUNT_4_BIT, TEST_SUBTYPE_MSAA_SAMPLE_QUALIFIER },
1903 };
1904
1905 MovePtr<tcu::TestCaseGroup> testTypeGroup (new tcu::TestCaseGroup(testCtx, "weights"));
1906 const TestType testType = TEST_TYPE_WEIGHTS;
1907
1908 for (size_t topologyInPipelineNdx = 0; topologyInPipelineNdx < DE_LENGTH_OF_ARRAY(topologiesInPipeline); ++topologyInPipelineNdx)
1909 {
1910 MovePtr<tcu::TestCaseGroup> topologyInPipelineGroup (new tcu::TestCaseGroup(testCtx, topologiesInPipeline[topologyInPipelineNdx].name));
1911 const bool topologyInPipeline = topologiesInPipeline[topologyInPipelineNdx].value;
1912
1913 if (topologyInPipeline)
1914 {
1915 for (size_t msaaCaseNdx = 0; msaaCaseNdx < DE_LENGTH_OF_ARRAY(msaaCases); ++msaaCaseNdx)
1916 {
1917 MovePtr<tcu::TestCaseGroup> msaaGroup(new tcu::TestCaseGroup(testCtx, msaaCases[msaaCaseNdx].name));
1918 for (size_t topologyNdx = 0; topologyNdx < DE_LENGTH_OF_ARRAY(topologies); ++topologyNdx)
1919 {
1920 MovePtr<tcu::TestCaseGroup> topologyGroup(new tcu::TestCaseGroup(testCtx, topologies[topologyNdx].name));
1921 const VkPrimitiveTopology topology = topologies[topologyNdx].topology;
1922 const bool testableTopology = isPrimitiveTopologyLine(topology) || isPrimitiveTopologyTriangle(topology);
1923
1924 if (!testableTopology)
1925 continue;
1926
1927 for (size_t perspectiveNdx = 0; perspectiveNdx < DE_LENGTH_OF_ARRAY(perspectives); ++perspectiveNdx)
1928 {
1929 const bool perspective = perspectives[perspectiveNdx].value;
1930 const char* perspectiveName = perspectives[perspectiveNdx].name;
1931
1932 const TestParams testParams
1933 {
1934 constructionTypeCase.constructionType,
1935 testType, // TestType testType;
1936 msaaCases[msaaCaseNdx].subtype, // TestSubtype testSubtype;
1937 topology, // VkPrimitiveTopology topology;
1938 notused, // bool dynamicIndexing;
1939 (size_t)notused, // size_t aggregate;
1940 (glu::DataType)notused, // glu::DataType dataType;
1941 WEIGHT_TEST_WIDTH, // uint32_t width;
1942 WEIGHT_TEST_HEIGHT, // uint32_t height;
1943 perspective, // bool perspective;
1944 false, // bool provokingVertexLast;
1945 0, // uint32_t rotation;
1946 topologyInPipeline, // bool dynamicTopologyInPipeline
1947 msaaCases[msaaCaseNdx].samples, // VkSampleCountFlagBits sampleCount;
1948 };
1949
1950 topologyGroup->addChild(new FragmentShadingBarycentricTestCase(testCtx, perspectiveName, testParams));
1951 }
1952 msaaGroup->addChild(topologyGroup.release());
1953 }
1954 topologyInPipelineGroup->addChild(msaaGroup.release());
1955 }
1956 }
1957 else
1958 {
1959 for (size_t rotationNdx = 0; rotationNdx < DE_LENGTH_OF_ARRAY(rotations); ++rotationNdx)
1960 {
1961 const uint32_t rotation = rotations[rotationNdx];
1962 MovePtr<tcu::TestCaseGroup> rotationGroup (new tcu::TestCaseGroup(testCtx, de::toString(rotation).c_str()));
1963
1964 for (size_t topologyNdx = 0; topologyNdx < DE_LENGTH_OF_ARRAY(topologies); ++topologyNdx)
1965 {
1966 const VkPrimitiveTopology topology = topologies[topologyNdx].topology;
1967 MovePtr<tcu::TestCaseGroup> topologyGroup (new tcu::TestCaseGroup(testCtx, topologies[topologyNdx].name));
1968
1969 for (size_t perspectiveNdx = 0; perspectiveNdx < DE_LENGTH_OF_ARRAY(perspectives); ++perspectiveNdx)
1970 {
1971 const bool perspective = perspectives[perspectiveNdx].value;
1972 const char* perspectiveName = perspectives[perspectiveNdx].name;
1973
1974 const TestParams testParams
1975 {
1976 constructionTypeCase.constructionType,
1977 testType, // TestType testType;
1978 TEST_SUBTYPE_DEFAULT, // TestSubtype testSubtype;
1979 topology, // VkPrimitiveTopology topology;
1980 notused, // bool dynamicIndexing;
1981 (size_t)-1, // size_t aggregate;
1982 glu::TYPE_INVALID, // glu::DataType dataType;
1983 WEIGHT_TEST_WIDTH, // uint32_t width;
1984 WEIGHT_TEST_HEIGHT, // uint32_t height;
1985 perspective, // bool perspective;
1986 false, // bool provokingVertexLast;
1987 rotation, // uint32_t rotation;
1988 topologyInPipeline, // bool dynamicTopologyInPipeline
1989 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits sampleCount;
1990 };
1991
1992 topologyGroup->addChild(new FragmentShadingBarycentricTestCase(testCtx, perspectiveName, testParams));
1993 }
1994
1995 rotationGroup->addChild(topologyGroup.release());
1996 }
1997
1998 topologyInPipelineGroup->addChild(rotationGroup.release());
1999 }
2000 }
2001
2002 testTypeGroup->addChild(topologyInPipelineGroup.release());
2003 }
2004
2005 constructionTypeCase.testGroup->addChild(testTypeGroup.release());
2006 }
2007
2008 group->addChild(libGroup.release());
2009 group->addChild(fastLinkGroup.release());
2010
2011 return group.release();
2012 }
2013
2014 } // FragmentShadingBarycentric
2015 } // vkt
2016