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