1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2015 The Khronos Group Inc.
6 * Copyright (c) 2015 Imagination Technologies Ltd.
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 *
20 *//*!
21 * \file
22 * \brief Input Assembly Tests
23 *//*--------------------------------------------------------------------*/
24
25 #include "vktPipelineInputAssemblyTests.hpp"
26 #include "vktPipelineClearUtil.hpp"
27 #include "vktPipelineImageUtil.hpp"
28 #include "vktPipelineVertexUtil.hpp"
29 #include "vktPipelineReferenceRenderer.hpp"
30 #include "vktTestCase.hpp"
31 #include "vkImageUtil.hpp"
32 #include "vkMemUtil.hpp"
33 #include "vkPrograms.hpp"
34 #include "vkQueryUtil.hpp"
35 #include "vkRef.hpp"
36 #include "vkRefUtil.hpp"
37 #include "vkTypeUtil.hpp"
38 #include "vkCmdUtil.hpp"
39 #include "vkObjUtil.hpp"
40 #include "tcuImageCompare.hpp"
41 #include "deMath.h"
42 #include "deMemory.h"
43 #include "deRandom.hpp"
44 #include "deStringUtil.hpp"
45 #include "deUniquePtr.hpp"
46
47 #include <algorithm>
48 #include <sstream>
49 #include <vector>
50
51 namespace vkt
52 {
53 namespace pipeline
54 {
55
56 using namespace vk;
57
58 namespace
59 {
60
61 class InputAssemblyTest : public vkt::TestCase
62 {
63 public:
64 const static VkPrimitiveTopology s_primitiveTopologies[];
65 const static deUint32 s_restartIndex32;
66 const static deUint16 s_restartIndex16;
67
68 InputAssemblyTest (tcu::TestContext& testContext,
69 const std::string& name,
70 const std::string& description,
71 VkPrimitiveTopology primitiveTopology,
72 int primitiveCount,
73 bool testPrimitiveRestart,
74 VkIndexType indexType);
~InputAssemblyTest(void)75 virtual ~InputAssemblyTest (void) {}
76 virtual void initPrograms (SourceCollections& sourceCollections) const;
77 virtual TestInstance* createInstance (Context& context) const;
78 static bool isRestartIndex (VkIndexType indexType, deUint32 indexValue);
79 static deUint32 getRestartIndex (VkIndexType indexType);
80
81 protected:
82 virtual void createBufferData (VkPrimitiveTopology topology,
83 int primitiveCount,
84 VkIndexType indexType,
85 std::vector<deUint32>& indexData,
86 std::vector<Vertex4RGBA>& vertexData) const = 0;
87
88 private:
89 VkPrimitiveTopology m_primitiveTopology;
90 const int m_primitiveCount;
91 bool m_testPrimitiveRestart;
92 VkIndexType m_indexType;
93 };
94
95 class PrimitiveTopologyTest : public InputAssemblyTest
96 {
97 public:
98 PrimitiveTopologyTest (tcu::TestContext& testContext,
99 const std::string& name,
100 const std::string& description,
101 VkPrimitiveTopology primitiveTopology);
~PrimitiveTopologyTest(void)102 virtual ~PrimitiveTopologyTest (void) {}
103
104 protected:
105 virtual void createBufferData (VkPrimitiveTopology topology,
106 int primitiveCount,
107 VkIndexType indexType,
108 std::vector<deUint32>& indexData,
109 std::vector<Vertex4RGBA>& vertexData) const;
110
111 private:
112 };
113
114 class PrimitiveRestartTest : public InputAssemblyTest
115 {
116 public:
117 PrimitiveRestartTest (tcu::TestContext& testContext,
118 const std::string& name,
119 const std::string& description,
120 VkPrimitiveTopology primitiveTopology,
121 VkIndexType indexType);
~PrimitiveRestartTest(void)122 virtual ~PrimitiveRestartTest (void) {}
123
124 protected:
125 virtual void createBufferData (VkPrimitiveTopology topology,
126 int primitiveCount,
127 VkIndexType indexType,
128 std::vector<deUint32>& indexData,
129 std::vector<Vertex4RGBA>& vertexData) const;
130
131 private:
132 bool isRestartPrimitive (int primitiveIndex) const;
133
134 std::vector<deUint32> m_restartPrimitives;
135 };
136
137 class InputAssemblyInstance : public vkt::TestInstance
138 {
139 public:
140 InputAssemblyInstance (Context& context,
141 VkPrimitiveTopology primitiveTopology,
142 bool testPrimitiveRestart,
143 VkIndexType indexType,
144 const std::vector<deUint32>& indexBufferData,
145 const std::vector<Vertex4RGBA>& vertexBufferData);
146 virtual ~InputAssemblyInstance (void);
147 virtual tcu::TestStatus iterate (void);
148
149 private:
150 tcu::TestStatus verifyImage (void);
151 void uploadIndexBufferData16 (deUint16* destPtr, const std::vector<deUint32>& indexBufferData);
152
153 VkPrimitiveTopology m_primitiveTopology;
154 bool m_primitiveRestartEnable;
155 VkIndexType m_indexType;
156
157 Move<VkBuffer> m_vertexBuffer;
158 std::vector<Vertex4RGBA> m_vertices;
159 de::MovePtr<Allocation> m_vertexBufferAlloc;
160
161 Move<VkBuffer> m_indexBuffer;
162 std::vector<deUint32> m_indices;
163 de::MovePtr<Allocation> m_indexBufferAlloc;
164
165 const tcu::UVec2 m_renderSize;
166
167 const VkFormat m_colorFormat;
168 VkImageCreateInfo m_colorImageCreateInfo;
169 Move<VkImage> m_colorImage;
170 de::MovePtr<Allocation> m_colorImageAlloc;
171 Move<VkImageView> m_colorAttachmentView;
172 Move<VkRenderPass> m_renderPass;
173 Move<VkFramebuffer> m_framebuffer;
174
175 Move<VkShaderModule> m_vertexShaderModule;
176 Move<VkShaderModule> m_fragmentShaderModule;
177
178 Move<VkPipelineLayout> m_pipelineLayout;
179 Move<VkPipeline> m_graphicsPipeline;
180
181 Move<VkCommandPool> m_cmdPool;
182 Move<VkCommandBuffer> m_cmdBuffer;
183 };
184
185
186 // InputAssemblyTest
187
188 const VkPrimitiveTopology InputAssemblyTest::s_primitiveTopologies[] =
189 {
190 VK_PRIMITIVE_TOPOLOGY_POINT_LIST,
191 VK_PRIMITIVE_TOPOLOGY_LINE_LIST,
192 VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,
193 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
194 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
195 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,
196 VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY,
197 VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY,
198 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY,
199 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY
200 };
201
202 const deUint32 InputAssemblyTest::s_restartIndex32 = ~((deUint32)0u);
203 const deUint16 InputAssemblyTest::s_restartIndex16 = ~((deUint16)0u);
204
InputAssemblyTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,VkPrimitiveTopology primitiveTopology,int primitiveCount,bool testPrimitiveRestart,VkIndexType indexType)205 InputAssemblyTest::InputAssemblyTest (tcu::TestContext& testContext,
206 const std::string& name,
207 const std::string& description,
208 VkPrimitiveTopology primitiveTopology,
209 int primitiveCount,
210 bool testPrimitiveRestart,
211 VkIndexType indexType)
212
213 : vkt::TestCase (testContext, name, description)
214 , m_primitiveTopology (primitiveTopology)
215 , m_primitiveCount (primitiveCount)
216 , m_testPrimitiveRestart (testPrimitiveRestart)
217 , m_indexType (indexType)
218 {
219 }
220
createInstance(Context & context) const221 TestInstance* InputAssemblyTest::createInstance (Context& context) const
222 {
223 std::vector<deUint32> indexBufferData;
224 std::vector<Vertex4RGBA> vertexBufferData;
225
226 createBufferData(m_primitiveTopology, m_primitiveCount, m_indexType, indexBufferData, vertexBufferData);
227
228 return new InputAssemblyInstance(context, m_primitiveTopology, m_testPrimitiveRestart, m_indexType, indexBufferData, vertexBufferData);
229 }
230
initPrograms(SourceCollections & sourceCollections) const231 void InputAssemblyTest::initPrograms (SourceCollections& sourceCollections) const
232 {
233 std::ostringstream vertexSource;
234
235 vertexSource <<
236 "#version 310 es\n"
237 "layout(location = 0) in vec4 position;\n"
238 "layout(location = 1) in vec4 color;\n"
239 "layout(location = 0) out highp vec4 vtxColor;\n"
240 "void main (void)\n"
241 "{\n"
242 " gl_Position = position;\n"
243 << (m_primitiveTopology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST ? " gl_PointSize = 3.0;\n"
244 : "" )
245 << " vtxColor = color;\n"
246 "}\n";
247
248 sourceCollections.glslSources.add("color_vert") << glu::VertexSource(vertexSource.str());
249
250 sourceCollections.glslSources.add("color_frag") << glu::FragmentSource(
251 "#version 310 es\n"
252 "layout(location = 0) in highp vec4 vtxColor;\n"
253 "layout(location = 0) out highp vec4 fragColor;\n"
254 "void main (void)\n"
255 "{\n"
256 " fragColor = vtxColor;\n"
257 "}\n");
258 }
259
isRestartIndex(VkIndexType indexType,deUint32 indexValue)260 bool InputAssemblyTest::isRestartIndex (VkIndexType indexType, deUint32 indexValue)
261 {
262 if (indexType == VK_INDEX_TYPE_UINT32)
263 return indexValue == s_restartIndex32;
264 else
265 return indexValue == s_restartIndex16;
266 }
267
getRestartIndex(VkIndexType indexType)268 deUint32 InputAssemblyTest::getRestartIndex (VkIndexType indexType)
269 {
270 if (indexType == VK_INDEX_TYPE_UINT16)
271 return InputAssemblyTest::s_restartIndex16;
272 else
273 return InputAssemblyTest::s_restartIndex32;
274 }
275
276
277 // PrimitiveTopologyTest
278
PrimitiveTopologyTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,VkPrimitiveTopology primitiveTopology)279 PrimitiveTopologyTest::PrimitiveTopologyTest (tcu::TestContext& testContext,
280 const std::string& name,
281 const std::string& description,
282 VkPrimitiveTopology primitiveTopology)
283 : InputAssemblyTest (testContext, name, description, primitiveTopology, 10, false, VK_INDEX_TYPE_UINT32)
284 {
285 }
286
createBufferData(VkPrimitiveTopology topology,int primitiveCount,VkIndexType indexType,std::vector<deUint32> & indexData,std::vector<Vertex4RGBA> & vertexData) const287 void PrimitiveTopologyTest::createBufferData (VkPrimitiveTopology topology, int primitiveCount, VkIndexType indexType, std::vector<deUint32>& indexData, std::vector<Vertex4RGBA>& vertexData) const
288 {
289 DE_ASSERT(primitiveCount > 0);
290 DE_UNREF(indexType);
291
292 const tcu::Vec4 red (1.0f, 0.0f, 0.0f, 1.0f);
293 const tcu::Vec4 green (0.0f, 1.0f, 0.0f, 1.0f);
294 const float border = 0.2f;
295 const float originX = -1.0f + border;
296 const float originY = -1.0f + border;
297 const Vertex4RGBA defaultVertex = { tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), green };
298 float primitiveSizeY = (2.0f - 2.0f * border);
299 float primitiveSizeX;
300 std::vector<deUint32> indices;
301 std::vector<Vertex4RGBA> vertices;
302
303
304 // Calculate primitive size
305 switch (topology)
306 {
307 case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
308 primitiveSizeX = (2.0f - 2.0f * border) / float(primitiveCount / 2 + primitiveCount % 2 - 1);
309 break;
310
311 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
312 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
313 primitiveSizeX = (2.0f - 2.0f * border) / float(primitiveCount - 1);
314 break;
315
316 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
317 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
318 primitiveSizeX = (2.0f - 2.0f * border) / float(primitiveCount / 2);
319 break;
320
321 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
322 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
323 primitiveSizeX = (2.0f - 2.0f * border) / float(primitiveCount + primitiveCount / 2 + primitiveCount % 2 - 1);
324 break;
325
326 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
327 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
328 primitiveSizeX = (2.0f - 2.0f * border) / float(primitiveCount / 2 + primitiveCount % 2);
329 break;
330
331 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
332 primitiveSizeX = 1.0f - border;
333 primitiveSizeY = 1.0f - border;
334 break;
335
336 default:
337 primitiveSizeX = 0.0f; // Garbage
338 DE_ASSERT(false);
339 }
340
341 switch (topology)
342 {
343 case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
344 for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++)
345 {
346 const Vertex4RGBA vertex =
347 {
348 tcu::Vec4(originX + float(primitiveNdx / 2) * primitiveSizeX, originY + float(primitiveNdx % 2) * primitiveSizeY, 0.0f, 1.0f),
349 red
350 };
351
352 vertices.push_back(vertex);
353 indices.push_back(primitiveNdx);
354 }
355 break;
356
357 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
358 for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++)
359 {
360 for (int vertexNdx = 0; vertexNdx < 2; vertexNdx++)
361 {
362 const Vertex4RGBA vertex =
363 {
364 tcu::Vec4(originX + float((primitiveNdx * 2 + vertexNdx) / 2) * primitiveSizeX, originY + float(vertexNdx % 2) * primitiveSizeY, 0.0f, 1.0f),
365 red
366 };
367
368 vertices.push_back(vertex);
369 indices.push_back((primitiveNdx * 2 + vertexNdx));
370 }
371 }
372 break;
373
374 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
375 for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++)
376 {
377 if (primitiveNdx == 0)
378 {
379 Vertex4RGBA vertex =
380 {
381 tcu::Vec4(originX, originY, 0.0f, 1.0f),
382 red
383 };
384
385 vertices.push_back(vertex);
386 indices.push_back(0);
387
388 vertex.position = tcu::Vec4(originX, originY + primitiveSizeY, 0.0f, 1.0f);
389 vertices.push_back(vertex);
390 indices.push_back(1);
391 }
392 else
393 {
394 const Vertex4RGBA vertex =
395 {
396 tcu::Vec4(originX + float((primitiveNdx + 1) / 2) * primitiveSizeX, originY + float((primitiveNdx + 1) % 2) * primitiveSizeY, 0.0f, 1.0f),
397 red
398 };
399
400 vertices.push_back(vertex);
401 indices.push_back(primitiveNdx + 1);
402 }
403 }
404 break;
405
406 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
407 for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++)
408 {
409 for (int vertexNdx = 0; vertexNdx < 3; vertexNdx++)
410 {
411 const Vertex4RGBA vertex =
412 {
413 tcu::Vec4(originX + float((primitiveNdx * 3 + vertexNdx) / 2) * primitiveSizeX, originY + float((primitiveNdx * 3 + vertexNdx)% 2) * primitiveSizeY, 0.0f, 1.0f),
414 red
415 };
416
417 vertices.push_back(vertex);
418 indices.push_back(primitiveNdx * 3 + vertexNdx);
419 }
420 }
421 break;
422
423 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
424 for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++)
425 {
426 if (primitiveNdx == 0)
427 {
428 for (int vertexNdx = 0; vertexNdx < 3; vertexNdx++)
429 {
430 const Vertex4RGBA vertex =
431 {
432 tcu::Vec4(originX + float(vertexNdx / 2) * primitiveSizeX, originY + float(vertexNdx % 2) * primitiveSizeY, 0.0f, 1.0f),
433 red
434 };
435
436 vertices.push_back(vertex);
437 indices.push_back(vertexNdx);
438 }
439 }
440 else
441 {
442 const Vertex4RGBA vertex =
443 {
444 tcu::Vec4(originX + float((primitiveNdx + 2) / 2) * primitiveSizeX, originY + float((primitiveNdx + 2) % 2) * primitiveSizeY, 0.0f, 1.0f),
445 red
446 };
447
448 vertices.push_back(vertex);
449 indices.push_back(primitiveNdx + 2);
450 }
451 }
452 break;
453
454 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
455 {
456 const float stepAngle = de::min(DE_PI * 0.5f, (2 * DE_PI) / float(primitiveCount));
457
458 for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++)
459 {
460 if (primitiveNdx == 0)
461 {
462 Vertex4RGBA vertex =
463 {
464 tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f),
465 red
466 };
467
468 vertices.push_back(vertex);
469 indices.push_back(0);
470
471 vertex.position = tcu::Vec4(primitiveSizeX, 0.0f, 0.0f, 1.0f);
472 vertices.push_back(vertex);
473 indices.push_back(1);
474
475 vertex.position = tcu::Vec4(primitiveSizeX * deFloatCos(stepAngle), primitiveSizeY * deFloatSin(stepAngle), 0.0f, 1.0f);
476 vertices.push_back(vertex);
477 indices.push_back(2);
478 }
479 else
480 {
481 const Vertex4RGBA vertex =
482 {
483 tcu::Vec4(primitiveSizeX * deFloatCos(stepAngle * float(primitiveNdx + 1)), primitiveSizeY * deFloatSin(stepAngle * float(primitiveNdx + 1)), 0.0f, 1.0f),
484 red
485 };
486
487 vertices.push_back(vertex);
488 indices.push_back(primitiveNdx + 2);
489 }
490 }
491 break;
492 }
493
494 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
495 vertices.push_back(defaultVertex);
496
497 for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++)
498 {
499 indices.push_back(0);
500
501 for (int vertexNdx = 0; vertexNdx < 2; vertexNdx++)
502 {
503 const Vertex4RGBA vertex =
504 {
505 tcu::Vec4(originX + float((primitiveNdx * 2 + vertexNdx) / 2) * primitiveSizeX, originY + float(vertexNdx % 2) * primitiveSizeY, 0.0f, 1.0f),
506 red
507 };
508
509 vertices.push_back(vertex);
510 indices.push_back(primitiveNdx * 2 + vertexNdx + 1);
511 }
512
513 indices.push_back(0);
514 }
515 break;
516
517
518 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
519 vertices.push_back(defaultVertex);
520 indices.push_back(0);
521
522 for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++)
523 {
524 if (primitiveNdx == 0)
525 {
526 Vertex4RGBA vertex =
527 {
528 tcu::Vec4(originX, originY, 0.0f, 1.0f),
529 red
530 };
531
532 vertices.push_back(vertex);
533 indices.push_back(1);
534
535 vertex.position = tcu::Vec4(originX, originY + primitiveSizeY, 0.0f, 1.0f);
536 vertices.push_back(vertex);
537 indices.push_back(2);
538 }
539 else
540 {
541 const Vertex4RGBA vertex =
542 {
543 tcu::Vec4(originX + float((primitiveNdx + 1) / 2) * primitiveSizeX, originY + float((primitiveNdx + 1) % 2) * primitiveSizeY, 0.0f, 1.0f),
544 red
545 };
546
547 vertices.push_back(vertex);
548 indices.push_back(primitiveNdx + 2);
549 }
550 }
551
552 indices.push_back(0);
553 break;
554
555 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
556 vertices.push_back(defaultVertex);
557
558 for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++)
559 {
560 for (int vertexNdx = 0; vertexNdx < 3; vertexNdx++)
561 {
562 const Vertex4RGBA vertex =
563 {
564 tcu::Vec4(originX + float((primitiveNdx * 3 + vertexNdx) / 2) * primitiveSizeX, originY + float((primitiveNdx * 3 + vertexNdx)% 2) * primitiveSizeY, 0.0f, 1.0f),
565 red
566 };
567
568 vertices.push_back(vertex);
569 indices.push_back(primitiveNdx * 3 + vertexNdx + 1);
570 indices.push_back(0);
571 }
572 }
573 break;
574
575 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
576 vertices.push_back(defaultVertex);
577
578 for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++)
579 {
580 if (primitiveNdx == 0)
581 {
582 for (int vertexNdx = 0; vertexNdx < 3; vertexNdx++)
583 {
584 const Vertex4RGBA vertex =
585 {
586 tcu::Vec4(originX + float(vertexNdx / 2) * primitiveSizeX, originY + float(vertexNdx % 2) * primitiveSizeY, 0.0f, 1.0f),
587 red
588 };
589
590 vertices.push_back(vertex);
591 indices.push_back(vertexNdx + 1);
592 indices.push_back(0);
593 }
594 }
595 else
596 {
597 const Vertex4RGBA vertex =
598 {
599 tcu::Vec4(originX + float((primitiveNdx + 2) / 2) * primitiveSizeX, originY + float((primitiveNdx + 2) % 2) * primitiveSizeY, 0.0f, 1.0f),
600 red
601 };
602
603 vertices.push_back(vertex);
604 indices.push_back(primitiveNdx + 2 + 1);
605 indices.push_back(0);
606 }
607 }
608 break;
609
610 default:
611 DE_ASSERT(false);
612 break;
613 }
614
615 vertexData = vertices;
616 indexData = indices;
617 }
618
619
620 // PrimitiveRestartTest
621
PrimitiveRestartTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,VkPrimitiveTopology primitiveTopology,VkIndexType indexType)622 PrimitiveRestartTest::PrimitiveRestartTest (tcu::TestContext& testContext,
623 const std::string& name,
624 const std::string& description,
625 VkPrimitiveTopology primitiveTopology,
626 VkIndexType indexType)
627
628 : InputAssemblyTest (testContext, name, description, primitiveTopology, 10, true, indexType)
629 {
630 DE_ASSERT(primitiveTopology == VK_PRIMITIVE_TOPOLOGY_LINE_STRIP ||
631 primitiveTopology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP ||
632 primitiveTopology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN ||
633 primitiveTopology == VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY ||
634 primitiveTopology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY);
635
636 deUint32 restartPrimitives[] = { 1, 5 };
637
638 m_restartPrimitives = std::vector<deUint32>(restartPrimitives, restartPrimitives + sizeof(restartPrimitives) / sizeof(deUint32));
639 }
640
createBufferData(VkPrimitiveTopology topology,int primitiveCount,VkIndexType indexType,std::vector<deUint32> & indexData,std::vector<Vertex4RGBA> & vertexData) const641 void PrimitiveRestartTest::createBufferData (VkPrimitiveTopology topology, int primitiveCount, VkIndexType indexType, std::vector<deUint32>& indexData, std::vector<Vertex4RGBA>& vertexData) const
642 {
643 DE_ASSERT(primitiveCount > 0);
644 DE_UNREF(indexType);
645
646 const tcu::Vec4 red (1.0f, 0.0f, 0.0f, 1.0f);
647 const tcu::Vec4 green (0.0f, 1.0f, 0.0f, 1.0f);
648 const float border = 0.2f;
649 const float originX = -1.0f + border;
650 const float originY = -1.0f + border;
651 const Vertex4RGBA defaultVertex = { tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), green };
652 float primitiveSizeY = (2.0f - 2.0f * border);
653 float primitiveSizeX;
654 bool primitiveStart = true;
655 std::vector<deUint32> indices;
656 std::vector<Vertex4RGBA> vertices;
657
658
659 // Calculate primitive size
660 switch (topology)
661 {
662 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
663 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
664 primitiveSizeX = (2.0f - 2.0f * border) / float(primitiveCount / 2);
665 break;
666
667 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
668 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
669 primitiveSizeX = (2.0f - 2.0f * border) / float(primitiveCount / 2 + primitiveCount % 2);
670 break;
671
672 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
673 primitiveSizeX = 1.0f - border;
674 primitiveSizeY = 1.0f - border;
675 break;
676
677 default:
678 primitiveSizeX = 0.0f; // Garbage
679 DE_ASSERT(false);
680 }
681
682 switch (topology)
683 {
684 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
685 for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++)
686 {
687 if (isRestartPrimitive(primitiveNdx))
688 {
689 indices.push_back(InputAssemblyTest::getRestartIndex(indexType));
690 primitiveStart = true;
691 }
692 else
693 {
694 if (primitiveStart)
695 {
696 const Vertex4RGBA vertex =
697 {
698 tcu::Vec4(originX + float(primitiveNdx / 2) * primitiveSizeX, originY + float(primitiveNdx % 2) * primitiveSizeY, 0.0f, 1.0f),
699 red
700 };
701
702 vertices.push_back(vertex);
703 indices.push_back((deUint32)vertices.size() - 1);
704
705 primitiveStart = false;
706 }
707
708 const Vertex4RGBA vertex =
709 {
710 tcu::Vec4(originX + float((primitiveNdx + 1) / 2) * primitiveSizeX, originY + float((primitiveNdx + 1) % 2) * primitiveSizeY, 0.0f, 1.0f),
711 red
712 };
713
714 vertices.push_back(vertex);
715 indices.push_back((deUint32)vertices.size() - 1);
716 }
717 }
718 break;
719
720 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
721 {
722 for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++)
723 {
724 if (isRestartPrimitive(primitiveNdx))
725 {
726 indices.push_back(InputAssemblyTest::getRestartIndex(indexType));
727 primitiveStart = true;
728 }
729 else
730 {
731 if (primitiveStart)
732 {
733 for (int vertexNdx = 0; vertexNdx < 2; vertexNdx++)
734 {
735 const Vertex4RGBA vertex =
736 {
737 tcu::Vec4(originX + float((primitiveNdx + vertexNdx) / 2) * primitiveSizeX, originY + float((primitiveNdx + vertexNdx) % 2) * primitiveSizeY, 0.0f, 1.0f),
738 red
739 };
740
741 vertices.push_back(vertex);
742 indices.push_back((deUint32)vertices.size() - 1);
743 }
744
745 primitiveStart = false;
746 }
747 const Vertex4RGBA vertex =
748 {
749 tcu::Vec4(originX + float((primitiveNdx + 2) / 2) * primitiveSizeX, originY + float((primitiveNdx + 2) % 2) * primitiveSizeY, 0.0f, 1.0f),
750 red
751 };
752
753 vertices.push_back(vertex);
754 indices.push_back((deUint32)vertices.size() - 1);
755 }
756 }
757 break;
758 }
759
760 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
761 {
762 const float stepAngle = de::min(DE_PI * 0.5f, (2 * DE_PI) / float(primitiveCount));
763
764 for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++)
765 {
766 if (isRestartPrimitive(primitiveNdx))
767 {
768 indices.push_back(InputAssemblyTest::getRestartIndex(indexType));
769 primitiveStart = true;
770 }
771 else
772 {
773 if (primitiveStart)
774 {
775 Vertex4RGBA vertex =
776 {
777 tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f),
778 red
779 };
780
781 vertices.push_back(vertex);
782 indices.push_back((deUint32)vertices.size() - 1);
783
784 vertex.position = tcu::Vec4(primitiveSizeX * deFloatCos(stepAngle * float(primitiveNdx)), primitiveSizeY * deFloatSin(stepAngle * float(primitiveNdx)), 0.0f, 1.0f),
785 vertices.push_back(vertex);
786 indices.push_back((deUint32)vertices.size() - 1);
787
788 primitiveStart = false;
789 }
790
791 const Vertex4RGBA vertex =
792 {
793 tcu::Vec4(primitiveSizeX * deFloatCos(stepAngle * float(primitiveNdx + 1)), primitiveSizeY * deFloatSin(stepAngle * float(primitiveNdx + 1)), 0.0f, 1.0f),
794 red
795 };
796
797 vertices.push_back(vertex);
798 indices.push_back((deUint32)vertices.size() - 1);
799 }
800 }
801 break;
802 }
803
804 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
805 vertices.push_back(defaultVertex);
806
807 for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++)
808 {
809 if (isRestartPrimitive(primitiveNdx))
810 {
811 indices.push_back(0);
812 indices.push_back(InputAssemblyTest::getRestartIndex(indexType));
813 primitiveStart = true;
814 }
815 else
816 {
817 if (primitiveStart)
818 {
819 indices.push_back(0);
820
821 const Vertex4RGBA vertex =
822 {
823 tcu::Vec4(originX + float(primitiveNdx / 2) * primitiveSizeX, originY + float(primitiveNdx % 2) * primitiveSizeY, 0.0f, 1.0f),
824 red
825 };
826
827 vertices.push_back(vertex);
828 indices.push_back((deUint32)vertices.size() - 1);
829
830 primitiveStart = false;
831 }
832
833 const Vertex4RGBA vertex =
834 {
835 tcu::Vec4(originX + float((primitiveNdx + 1) / 2) * primitiveSizeX, originY + float((primitiveNdx + 1) % 2) * primitiveSizeY, 0.0f, 1.0f),
836 red
837 };
838
839 vertices.push_back(vertex);
840 indices.push_back((deUint32)vertices.size() - 1);
841 }
842 }
843
844 indices.push_back(0);
845 break;
846
847 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
848 vertices.push_back(defaultVertex);
849
850 for (int primitiveNdx = 0; primitiveNdx < primitiveCount; primitiveNdx++)
851 {
852 if (isRestartPrimitive(primitiveNdx))
853 {
854 indices.push_back(InputAssemblyTest::getRestartIndex(indexType));
855 primitiveStart = true;
856 }
857 else
858 {
859 if (primitiveStart)
860 {
861 for (int vertexNdx = 0; vertexNdx < 2; vertexNdx++)
862 {
863 const Vertex4RGBA vertex =
864 {
865 tcu::Vec4(originX + float((primitiveNdx + vertexNdx) / 2) * primitiveSizeX, originY + float((primitiveNdx + vertexNdx) % 2) * primitiveSizeY, 0.0f, 1.0f),
866 red
867 };
868
869 vertices.push_back(vertex);
870 indices.push_back((deUint32)vertices.size() - 1);
871 indices.push_back(0);
872 }
873
874 primitiveStart = false;
875 }
876
877 const Vertex4RGBA vertex =
878 {
879 tcu::Vec4(originX + float((primitiveNdx + 2) / 2) * primitiveSizeX, originY + float((primitiveNdx + 2) % 2) * primitiveSizeY, 0.0f, 1.0f),
880 red
881 };
882
883 vertices.push_back(vertex);
884 indices.push_back((deUint32)vertices.size() - 1);
885 indices.push_back(0);
886 }
887 }
888 break;
889
890 default:
891 DE_ASSERT(false);
892 break;
893 }
894
895 vertexData = vertices;
896 indexData = indices;
897 }
898
isRestartPrimitive(int primitiveIndex) const899 bool PrimitiveRestartTest::isRestartPrimitive (int primitiveIndex) const
900 {
901 return std::find(m_restartPrimitives.begin(), m_restartPrimitives.end(), primitiveIndex) != m_restartPrimitives.end();
902 }
903
904
905 // InputAssemblyInstance
906
InputAssemblyInstance(Context & context,VkPrimitiveTopology primitiveTopology,bool testPrimitiveRestart,VkIndexType indexType,const std::vector<deUint32> & indexBufferData,const std::vector<Vertex4RGBA> & vertexBufferData)907 InputAssemblyInstance::InputAssemblyInstance (Context& context,
908 VkPrimitiveTopology primitiveTopology,
909 bool testPrimitiveRestart,
910 VkIndexType indexType,
911 const std::vector<deUint32>& indexBufferData,
912 const std::vector<Vertex4RGBA>& vertexBufferData)
913
914 : vkt::TestInstance (context)
915 , m_primitiveTopology (primitiveTopology)
916 , m_primitiveRestartEnable (testPrimitiveRestart)
917 , m_indexType (indexType)
918 , m_vertices (vertexBufferData)
919 , m_indices (indexBufferData)
920 , m_renderSize ((primitiveTopology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN) ? tcu::UVec2(32, 32) : tcu::UVec2(64, 16))
921 , m_colorFormat (VK_FORMAT_R8G8B8A8_UNORM)
922 {
923 const DeviceInterface& vk = context.getDeviceInterface();
924 const VkDevice vkDevice = context.getDevice();
925 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
926 SimpleAllocator memAlloc (vk, vkDevice, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()));
927 const VkComponentMapping componentMappingRGBA = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
928
929 switch (m_primitiveTopology)
930 {
931 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
932 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
933 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
934 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
935 if (!context.getDeviceFeatures().geometryShader)
936 throw tcu::NotSupportedError("Geometry shaders are not supported");
937 break;
938
939 case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST:
940 if (!context.getDeviceFeatures().tessellationShader)
941 throw tcu::NotSupportedError("Tessellation shaders are not supported");
942 break;
943
944 default:
945 break;
946 }
947
948 // Create color image
949 {
950 const VkImageCreateInfo colorImageParams =
951 {
952 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
953 DE_NULL, // const void* pNext;
954 0u, // VkImageCreateFlags flags;
955 VK_IMAGE_TYPE_2D, // VkImageType imageType;
956 m_colorFormat, // VkFormat format;
957 { m_renderSize.x(), m_renderSize.y(), 1u }, // VkExtent3D extent;
958 1u, // deUint32 mipLevels;
959 1u, // deUint32 arrayLayers;
960 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
961 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
962 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage;
963 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
964 1u, // deUint32 queueFamilyIndexCount;
965 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
966 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
967 };
968
969 m_colorImageCreateInfo = colorImageParams;
970 m_colorImage = createImage(vk, vkDevice, &m_colorImageCreateInfo);
971
972 // Allocate and bind color image memory
973 m_colorImageAlloc = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any);
974 VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset()));
975 }
976
977 // Create color attachment view
978 {
979 const VkImageViewCreateInfo colorAttachmentViewParams =
980 {
981 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
982 DE_NULL, // const void* pNext;
983 0u, // VkImageViewCreateFlags flags;
984 *m_colorImage, // VkImage image;
985 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
986 m_colorFormat, // VkFormat format;
987 componentMappingRGBA, // VkComponentMapping components;
988 { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }, // VkImageSubresourceRange subresourceRange;
989 };
990
991 m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams);
992 }
993
994 // Create render pass
995 m_renderPass = makeRenderPass(vk, vkDevice, m_colorFormat);
996
997 // Create framebuffer
998 {
999 const VkFramebufferCreateInfo framebufferParams =
1000 {
1001 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
1002 DE_NULL, // const void* pNext;
1003 0u, // VkFramebufferCreateFlags flags;
1004 *m_renderPass, // VkRenderPass renderPass;
1005 1u, // deUint32 attachmentCount;
1006 &m_colorAttachmentView.get(), // const VkImageView* pAttachments;
1007 (deUint32)m_renderSize.x(), // deUint32 width;
1008 (deUint32)m_renderSize.y(), // deUint32 height;
1009 1u // deUint32 layers;
1010 };
1011
1012 m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
1013 }
1014
1015 // Create pipeline layout
1016 {
1017 const VkPipelineLayoutCreateInfo pipelineLayoutParams =
1018 {
1019 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
1020 DE_NULL, // const void* pNext;
1021 0u, // VkPipelineLayoutCreateFlags flags;
1022 0u, // deUint32 setLayoutCount;
1023 DE_NULL, // const VkDescriptorSetLayout* pSetLayouts;
1024 0u, // deUint32 pushConstantRangeCount;
1025 DE_NULL // const VkPushConstantRange* pPushConstantRanges;
1026 };
1027
1028 m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
1029 }
1030
1031 m_vertexShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_vert"), 0);
1032 m_fragmentShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_frag"), 0);
1033
1034 // Create pipeline
1035 {
1036 const VkPipelineShaderStageCreateInfo shaderStageParams[2] =
1037 {
1038 {
1039 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
1040 DE_NULL, // const void* pNext;
1041 0u, // VkPipelineShaderStageCreateFlags flags;
1042 VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage;
1043 *m_vertexShaderModule, // VkShaderModule module;
1044 "main", // const char* pName;
1045 DE_NULL // const VkSpecializationInfo* pSpecializationInfo;
1046 },
1047 {
1048 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
1049 DE_NULL, // const void* pNext;
1050 0u, // VkPipelineShaderStageCreateFlags flags;
1051 VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage;
1052 *m_fragmentShaderModule, // VkShaderModule module;
1053 "main", // const char* pName;
1054 DE_NULL // const VkSpecializationInfo* pSpecializationInfo;
1055 }
1056 };
1057
1058 const VkVertexInputBindingDescription vertexInputBindingDescription =
1059 {
1060 0u, // deUint32 binding;
1061 sizeof(Vertex4RGBA), // deUint32 stride;
1062 VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputRate inputRate;
1063 };
1064
1065 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] =
1066 {
1067 {
1068 0u, // deUint32 location;
1069 0u, // deUint32 binding;
1070 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
1071 0u // deUint32 offset;
1072 },
1073 {
1074 1u, // deUint32 location;
1075 0u, // deUint32 binding;
1076 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
1077 DE_OFFSET_OF(Vertex4RGBA, color), // deUint32 offset;
1078 }
1079 };
1080
1081 const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
1082 {
1083 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
1084 DE_NULL, // const void* pNext;
1085 0u, // VkPipelineVertexInputStateCreateFlags flags;
1086 1u, // deUint32 vertexBindingDescriptionCount;
1087 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
1088 2u, // deUint32 vertexAttributeDescriptionCount;
1089 vertexInputAttributeDescriptions // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
1090 };
1091
1092 const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateParams =
1093 {
1094 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
1095 DE_NULL, // const void* pNext;
1096 0u, // VkPipelineInputAssemblyStateCreateFlags flags;
1097 m_primitiveTopology, // VkPrimitiveTopology topology;
1098 m_primitiveRestartEnable // VkBool32 primitiveRestartEnable;
1099 };
1100
1101 const VkViewport viewport = makeViewport(m_renderSize);
1102 const VkRect2D scissor = makeRect2D(m_renderSize);
1103
1104 const VkPipelineViewportStateCreateInfo viewportStateParams =
1105 {
1106 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
1107 DE_NULL, // const void* pNext;
1108 0u, // VkPipelineViewportStateCreateFlags flags;
1109 1u, // deUint32 viewportCount;
1110 &viewport, // const VkViewport* pViewports;
1111 1u, // deUint32 scissorCount;
1112 &scissor, // const VkRect2D* pScissors;
1113 };
1114
1115 const VkPipelineRasterizationStateCreateInfo rasterStateParams =
1116 {
1117 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
1118 DE_NULL, // const void* pNext;
1119 0u, // VkPipelineRasterizationStateCreateFlags flags;
1120 false, // VkBool32 depthClampEnable;
1121 false, // VkBool32 rasterizerDiscardEnable;
1122 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode;
1123 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode;
1124 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
1125 VK_FALSE, // VkBool32 depthBiasEnable;
1126 0.0f, // float depthBiasConstantFactor;
1127 0.0f, // float depthBiasClamp;
1128 0.0f, // float depthBiasSlopeFactor;
1129 1.0f // float lineWidth;
1130 };
1131
1132 const VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
1133 {
1134 false, // VkBool32 blendEnable;
1135 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor;
1136 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor;
1137 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp;
1138 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor;
1139 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor;
1140 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp;
1141 VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | // VkColorComponentFlags colorWriteMask;
1142 VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT
1143 };
1144
1145 const VkPipelineColorBlendStateCreateInfo colorBlendStateParams =
1146 {
1147 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
1148 DE_NULL, // const void* pNext;
1149 0u, // VkPipelineColorBlendStateCreateFlags flags;
1150 false, // VkBool32 logicOpEnable;
1151 VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
1152 1u, // deUint32 attachmentCount;
1153 &colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments;
1154 { 0.0f, 0.0f, 0.0f, 0.0f } // float blendConstants[4];
1155 };
1156
1157 const VkPipelineMultisampleStateCreateInfo multisampleStateParams =
1158 {
1159 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
1160 DE_NULL, // const void* pNext;
1161 0u, // VkPipelineMultisampleStateCreateFlags flags;
1162 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
1163 false, // VkBool32 sampleShadingEnable;
1164 0.0f, // float minSampleShading;
1165 DE_NULL, // const VkSampleMask* pSampleMask;
1166 false, // VkBool32 alphaToCoverageEnable;
1167 false // VkBool32 alphaToOneEnable;
1168 };
1169
1170 VkPipelineDepthStencilStateCreateInfo depthStencilStateParams =
1171 {
1172 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
1173 DE_NULL, // const void* pNext;
1174 0u, // VkPipelineDepthStencilStateCreateFlags flags;
1175 false, // VkBool32 depthTestEnable;
1176 false, // VkBool32 depthWriteEnable;
1177 VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp;
1178 false, // VkBool32 depthBoundsTestEnable;
1179 false, // VkBool32 stencilTestEnable;
1180 // VkStencilOpState front;
1181 {
1182 VK_STENCIL_OP_KEEP, // VkStencilOp failOp;
1183 VK_STENCIL_OP_KEEP, // VkStencilOp passOp;
1184 VK_STENCIL_OP_KEEP, // VkStencilOp depthFailOp;
1185 VK_COMPARE_OP_NEVER, // VkCompareOp compareOp;
1186 0u, // deUint32 compareMask;
1187 0u, // deUint32 writeMask;
1188 0u, // deUint32 reference;
1189 },
1190 // VkStencilOpState back;
1191 {
1192 VK_STENCIL_OP_KEEP, // VkStencilOp failOp;
1193 VK_STENCIL_OP_KEEP, // VkStencilOp passOp;
1194 VK_STENCIL_OP_KEEP, // VkStencilOp depthFailOp;
1195 VK_COMPARE_OP_NEVER, // VkCompareOp compareOp;
1196 0u, // deUint32 compareMask;
1197 0u, // deUint32 writeMask;
1198 0u, // deUint32 reference;
1199 },
1200 0.0f, // float minDepthBounds;
1201 1.0f // float maxDepthBounds;
1202 };
1203
1204 const VkGraphicsPipelineCreateInfo graphicsPipelineParams =
1205 {
1206 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
1207 DE_NULL, // const void* pNext;
1208 0u, // VkPipelineCreateFlags flags;
1209 2u, // deUint32 stageCount;
1210 shaderStageParams, // const VkPipelineShaderStageCreateInfo* pStages;
1211 &vertexInputStateParams, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
1212 &inputAssemblyStateParams, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
1213 DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState;
1214 &viewportStateParams, // const VkPipelineViewportStateCreateInfo* pViewportState;
1215 &rasterStateParams, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState;
1216 &multisampleStateParams, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
1217 &depthStencilStateParams, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
1218 &colorBlendStateParams, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
1219 (const VkPipelineDynamicStateCreateInfo*)DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState;
1220 *m_pipelineLayout, // VkPipelineLayout layout;
1221 *m_renderPass, // VkRenderPass renderPass;
1222 0u, // deUint32 subpass;
1223 0u, // VkPipeline basePipelineHandle;
1224 0u // deInt32 basePipelineIndex;
1225 };
1226
1227 m_graphicsPipeline = createGraphicsPipeline(vk, vkDevice, DE_NULL, &graphicsPipelineParams);
1228 }
1229
1230 // Create vertex and index buffer
1231 {
1232 const VkBufferCreateInfo indexBufferParams =
1233 {
1234 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
1235 DE_NULL, // const void* pNext;
1236 0u, // VkBufferCreateFlags flags;
1237 m_indices.size() * sizeof(deUint32), // VkDeviceSize size;
1238 VK_BUFFER_USAGE_INDEX_BUFFER_BIT, // VkBufferUsageFlags usage;
1239 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1240 1u, // deUint32 queueFamilyIndexCount;
1241 &queueFamilyIndex // const deUint32* pQueueFamilyIndices;
1242 };
1243
1244 const VkBufferCreateInfo vertexBufferParams =
1245 {
1246 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
1247 DE_NULL, // const void* pNext;
1248 0u, // VkBufferCreateFlags flags;
1249 m_vertices.size() * sizeof(Vertex4RGBA), // VkDeviceSize size;
1250 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage;
1251 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1252 1u, // deUint32 queueFamilyIndexCount;
1253 &queueFamilyIndex // const deUint32* pQueueFamilyIndices;
1254 };
1255
1256 m_indexBuffer = createBuffer(vk, vkDevice, &indexBufferParams);
1257 m_indexBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_indexBuffer), MemoryRequirement::HostVisible);
1258
1259 VK_CHECK(vk.bindBufferMemory(vkDevice, *m_indexBuffer, m_indexBufferAlloc->getMemory(), m_indexBufferAlloc->getOffset()));
1260
1261 m_vertexBuffer = createBuffer(vk, vkDevice, &vertexBufferParams);
1262 m_vertexBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer), MemoryRequirement::HostVisible);
1263
1264 VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));
1265
1266 // Load vertices into index buffer
1267 if (m_indexType == VK_INDEX_TYPE_UINT32)
1268 {
1269 deMemcpy(m_indexBufferAlloc->getHostPtr(), m_indices.data(), m_indices.size() * sizeof(deUint32));
1270 }
1271 else // m_indexType == VK_INDEX_TYPE_UINT16
1272 {
1273 uploadIndexBufferData16((deUint16*)m_indexBufferAlloc->getHostPtr(), m_indices);
1274 }
1275
1276 // Load vertices into vertex buffer
1277 deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBA));
1278
1279 flushAlloc(vk, vkDevice, *m_indexBufferAlloc);
1280 flushAlloc(vk, vkDevice, *m_vertexBufferAlloc);
1281 }
1282
1283 // Create command pool
1284 m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
1285
1286 // Create command buffer
1287 {
1288 const VkClearValue attachmentClearValue = defaultClearValue(m_colorFormat);
1289
1290 const VkImageMemoryBarrier attachmentLayoutBarrier =
1291 {
1292 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1293 DE_NULL, // const void* pNext;
1294 0u, // VkAccessFlags srcAccessMask;
1295 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask;
1296 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
1297 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout;
1298 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1299 VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex;
1300 *m_colorImage, // VkImage image;
1301 { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }, // VkImageSubresourceRange subresourceRange;
1302 };
1303
1304 m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1305
1306 beginCommandBuffer(vk, *m_cmdBuffer, 0u);
1307
1308 vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (VkDependencyFlags)0,
1309 0u, DE_NULL, 0u, DE_NULL, 1u, &attachmentLayoutBarrier);
1310
1311 beginRenderPass(vk, *m_cmdBuffer, *m_renderPass, *m_framebuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()), attachmentClearValue);
1312
1313 const VkDeviceSize vertexBufferOffset = 0;
1314
1315 vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipeline);
1316 vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
1317 vk.cmdBindIndexBuffer(*m_cmdBuffer, *m_indexBuffer, 0, m_indexType);
1318 vk.cmdDrawIndexed(*m_cmdBuffer, (deUint32)m_indices.size(), 1, 0, 0, 0);
1319
1320 endRenderPass(vk, *m_cmdBuffer);
1321 endCommandBuffer(vk, *m_cmdBuffer);
1322 }
1323 }
1324
~InputAssemblyInstance(void)1325 InputAssemblyInstance::~InputAssemblyInstance (void)
1326 {
1327 }
1328
iterate(void)1329 tcu::TestStatus InputAssemblyInstance::iterate (void)
1330 {
1331 const DeviceInterface& vk = m_context.getDeviceInterface();
1332 const VkDevice vkDevice = m_context.getDevice();
1333 const VkQueue queue = m_context.getUniversalQueue();
1334
1335 submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
1336
1337 return verifyImage();
1338 }
1339
verifyImage(void)1340 tcu::TestStatus InputAssemblyInstance::verifyImage (void)
1341 {
1342 const tcu::TextureFormat tcuColorFormat = mapVkFormat(m_colorFormat);
1343 const tcu::TextureFormat tcuStencilFormat = tcu::TextureFormat();
1344 const ColorVertexShader vertexShader;
1345 const ColorFragmentShader fragmentShader (tcuColorFormat, tcuStencilFormat);
1346 const rr::Program program (&vertexShader, &fragmentShader);
1347 ReferenceRenderer refRenderer (m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat, tcuStencilFormat, &program);
1348 bool compareOk = false;
1349
1350 // Render reference image
1351 {
1352 const rr::PrimitiveType topology = mapVkPrimitiveTopology(m_primitiveTopology);
1353 rr::RenderState renderState (refRenderer.getViewportState());
1354
1355 if (m_primitiveTopology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST)
1356 renderState.point.pointSize = 3.0f;
1357
1358 if (m_primitiveRestartEnable)
1359 {
1360 std::vector<deUint32> indicesRange;
1361
1362 for (size_t indexNdx = 0; indexNdx < m_indices.size(); indexNdx++)
1363 {
1364 const bool isRestart = InputAssemblyTest::isRestartIndex(m_indexType, m_indices[indexNdx]);
1365
1366 if (!isRestart)
1367 indicesRange.push_back(m_indices[indexNdx]);
1368
1369 if (isRestart || indexNdx == (m_indices.size() - 1))
1370 {
1371 // Draw the range of indices found so far
1372
1373 std::vector<Vertex4RGBA> nonIndexedVertices;
1374 for (size_t i = 0; i < indicesRange.size(); i++)
1375 nonIndexedVertices.push_back(m_vertices[indicesRange[i]]);
1376
1377 refRenderer.draw(renderState, topology, nonIndexedVertices);
1378 indicesRange.clear();
1379 }
1380 }
1381 }
1382 else
1383 {
1384 std::vector<Vertex4RGBA> nonIndexedVertices;
1385 for (size_t i = 0; i < m_indices.size(); i++)
1386 nonIndexedVertices.push_back(m_vertices[m_indices[i]]);
1387
1388 refRenderer.draw(renderState, topology, nonIndexedVertices);
1389 }
1390 }
1391
1392 // Compare result with reference image
1393 {
1394 const DeviceInterface& vk = m_context.getDeviceInterface();
1395 const VkDevice vkDevice = m_context.getDevice();
1396 const VkQueue queue = m_context.getUniversalQueue();
1397 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1398 SimpleAllocator allocator (vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
1399 de::UniquePtr<tcu::TextureLevel> result (readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_colorImage, m_colorFormat, m_renderSize).release());
1400
1401 compareOk = tcu::intThresholdPositionDeviationCompare(m_context.getTestContext().getLog(),
1402 "IntImageCompare",
1403 "Image comparison",
1404 refRenderer.getAccess(),
1405 result->getAccess(),
1406 tcu::UVec4(2, 2, 2, 2),
1407 tcu::IVec3(1, 1, 0),
1408 true,
1409 tcu::COMPARE_LOG_RESULT);
1410 }
1411
1412 if (compareOk)
1413 return tcu::TestStatus::pass("Result image matches reference");
1414 else
1415 return tcu::TestStatus::fail("Image mismatch");
1416 }
1417
uploadIndexBufferData16(deUint16 * destPtr,const std::vector<deUint32> & indexBufferData)1418 void InputAssemblyInstance::uploadIndexBufferData16 (deUint16* destPtr, const std::vector<deUint32>& indexBufferData)
1419 {
1420 for (size_t i = 0; i < indexBufferData.size(); i++)
1421 {
1422 DE_ASSERT(indexBufferData[i] <= 0xFFFF);
1423 destPtr[i] = (deUint16)indexBufferData[i];
1424 }
1425 }
1426
1427
1428 // Utilities for test names
1429
getPrimitiveTopologyCaseName(VkPrimitiveTopology topology)1430 std::string getPrimitiveTopologyCaseName (VkPrimitiveTopology topology)
1431 {
1432 const std::string fullName = getPrimitiveTopologyName(topology);
1433
1434 DE_ASSERT(de::beginsWith(fullName, "VK_PRIMITIVE_TOPOLOGY_"));
1435
1436 return de::toLower(fullName.substr(22));
1437 }
1438
createPrimitiveTopologyTests(tcu::TestContext & testCtx)1439 de::MovePtr<tcu::TestCaseGroup> createPrimitiveTopologyTests (tcu::TestContext& testCtx)
1440 {
1441 de::MovePtr<tcu::TestCaseGroup> primitiveTopologyTests (new tcu::TestCaseGroup(testCtx, "primitive_topology", ""));
1442
1443 for (int topologyNdx = 0; topologyNdx < DE_LENGTH_OF_ARRAY(InputAssemblyTest::s_primitiveTopologies); topologyNdx++)
1444 {
1445 const VkPrimitiveTopology topology = InputAssemblyTest::s_primitiveTopologies[topologyNdx];
1446
1447 primitiveTopologyTests->addChild(new PrimitiveTopologyTest(testCtx,
1448 getPrimitiveTopologyCaseName(topology),
1449 "",
1450 topology));
1451 }
1452
1453 return primitiveTopologyTests;
1454 }
1455
createPrimitiveRestartTests(tcu::TestContext & testCtx)1456 de::MovePtr<tcu::TestCaseGroup> createPrimitiveRestartTests (tcu::TestContext& testCtx)
1457 {
1458 const VkPrimitiveTopology primitiveRestartTopologies[] =
1459 {
1460 VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,
1461 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
1462 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,
1463 VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY,
1464 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY
1465 };
1466
1467 de::MovePtr<tcu::TestCaseGroup> primitiveRestartTests (new tcu::TestCaseGroup(testCtx, "primitive_restart", "Restarts indices of "));
1468
1469 de::MovePtr<tcu::TestCaseGroup> indexUint16Tests (new tcu::TestCaseGroup(testCtx, "index_type_uint16", ""));
1470 de::MovePtr<tcu::TestCaseGroup> indexUint32Tests (new tcu::TestCaseGroup(testCtx, "index_type_uint32", ""));
1471
1472 for (int topologyNdx = 0; topologyNdx < DE_LENGTH_OF_ARRAY(primitiveRestartTopologies); topologyNdx++)
1473 {
1474 const VkPrimitiveTopology topology = primitiveRestartTopologies[topologyNdx];
1475
1476 indexUint16Tests->addChild(new PrimitiveRestartTest(testCtx,
1477 getPrimitiveTopologyCaseName(topology),
1478 "",
1479 topology,
1480 VK_INDEX_TYPE_UINT16));
1481
1482 indexUint32Tests->addChild(new PrimitiveRestartTest(testCtx,
1483 getPrimitiveTopologyCaseName(topology),
1484 "",
1485 topology,
1486 VK_INDEX_TYPE_UINT32));
1487 }
1488
1489 primitiveRestartTests->addChild(indexUint16Tests.release());
1490 primitiveRestartTests->addChild(indexUint32Tests.release());
1491
1492 return primitiveRestartTests;
1493 }
1494
1495 } // anonymous
1496
createInputAssemblyTests(tcu::TestContext & testCtx)1497 tcu::TestCaseGroup* createInputAssemblyTests (tcu::TestContext& testCtx)
1498 {
1499 de::MovePtr<tcu::TestCaseGroup> inputAssemblyTests (new tcu::TestCaseGroup(testCtx, "input_assembly", "Input assembly tests"));
1500
1501 inputAssemblyTests->addChild(createPrimitiveTopologyTests(testCtx).release());
1502 inputAssemblyTests->addChild(createPrimitiveRestartTests(testCtx).release());
1503
1504 return inputAssemblyTests.release();
1505 }
1506
1507 } // pipeline
1508 } // vkt
1509