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 vktPipelineInterfaceMatchingTests.cpp
21 * \brief Interface matching tests
22 *//*--------------------------------------------------------------------*/
23
24 #include "vktPipelineInterfaceMatchingTests.hpp"
25 #include "vktPipelineImageUtil.hpp"
26
27 #include "vkBuilderUtil.hpp"
28 #include "vkBarrierUtil.hpp"
29 #include "vkImageUtil.hpp"
30 #include "vkMemUtil.hpp"
31 #include "vkQueryUtil.hpp"
32 #include "vkTypeUtil.hpp"
33 #include "vkCmdUtil.hpp"
34 #include "vkObjUtil.hpp"
35
36 #include "tcuTestLog.hpp"
37 #include "tcuTestCase.hpp"
38 #include "tcuStringTemplate.hpp"
39
40 #include <set>
41
42 namespace vkt
43 {
44 namespace pipeline
45 {
46
47 using namespace vk;
48 using namespace de;
49 using namespace tcu;
50
51 namespace
52 {
53
54 enum class TestType
55 {
56 VECTOR_LENGTH = 0,
57 DECORATION_MISMATCH,
58 };
59
60 enum class VecType
61 {
62 VEC2 = 0,
63 VEC3,
64 VEC4,
65 IVEC2,
66 IVEC3,
67 IVEC4,
68 UVEC2,
69 UVEC3,
70 UVEC4,
71 };
72
73 enum class DecorationType
74 {
75 NONE = 0,
76 FLAT,
77 NO_PERSPECTIVE,
78 COMPONENT0
79 };
80
81 enum class PipelineType
82 {
83 // all combinations with vert and frag
84 VERT_OUT_FRAG_IN = 0,
85
86 // all combinations with vert, tesc, tese and frag
87 VERT_OUT_TESC_IN_TESE_FRAG,
88 VERT_TESC_TESE_OUT_FRAG_IN,
89 VERT_TESC_OUT_TESE_IN_FRAG,
90
91 // all combinations with vert, geom and frag
92 VERT_OUT_GEOM_IN_FRAG,
93 VERT_GEOM_OUT_FRAG_IN,
94
95 // all combinations with vert, tesc, tese, geom and frag
96 VERT_OUT_TESC_IN_TESE_GEOM_FRAG, // this won't add coverage as it is similar to VERT_OUT_TESC_IN_TESE_FRAG
97 //VERT_TESC_OUT_TESE_IN_GEOM_FRAG, // this won't add coverage as it is similar to VERT_TESC_OUT_TESE_IN_FRAG
98 VERT_TESC_TESE_OUT_GEOM_IN_FRAG,
99 VERT_TESC_TESE_GEOM_OUT_FRAG_IN,
100 };
101
102 enum class DefinitionType
103 {
104 LOOSE_VARIABLE = 0,
105 MEMBER_OF_BLOCK,
106 MEMBER_OF_STRUCTURE,
107 MEMBER_OF_ARRAY_OF_STRUCTURES,
108 MEMBER_OF_STRUCTURE_IN_BLOCK,
109 MEMBER_OF_ARRAY_OF_STRUCTURES_IN_BLOCK,
110 };
111
112 struct TestParams
113 {
114 TestType testType;
115
116 VecType outVecType;
117 VecType inVecType;
118
119 DecorationType outDeclDecoration;
120 DecorationType inDeclDecoration;
121
122 PipelineType pipelineType;
123 DefinitionType definitionType;
124 };
125
126 typedef de::SharedPtr<TestParams> TestParamsSp;
127
128 // helper function that check if specified pipeline is in set of pipelines
isPipelineOneOf(PipelineType pipelineType,std::set<PipelineType> pipelines)129 bool isPipelineOneOf(PipelineType pipelineType, std::set<PipelineType> pipelines)
130 {
131 return !!pipelines.count(pipelineType);
132 }
133
134 class InterfaceMatchingTestInstance : public vkt::TestInstance
135 {
136 public:
137 InterfaceMatchingTestInstance (Context& context,
138 const TestParamsSp params);
139 virtual ~InterfaceMatchingTestInstance (void) = default;
140
141 tcu::TestStatus iterate(void) override;
142
143 private:
144 TestParamsSp m_params;
145 SimpleAllocator m_alloc;
146
147 Move<VkBuffer> m_vertexBuffer;
148 de::MovePtr<Allocation> m_vertexBufferAlloc;
149 Move<VkBuffer> m_resultBuffer;
150 de::MovePtr<Allocation> m_resultBufferAlloc;
151
152 Move<VkImage> m_colorImage;
153 de::MovePtr<Allocation> m_colorImageAlloc;
154 Move<VkImageView> m_colorAttachmentView;
155 Move<VkRenderPass> m_renderPass;
156 Move<VkFramebuffer> m_framebuffer;
157
158 Move<VkShaderModule> m_vertShaderModule;
159 Move<VkShaderModule> m_tescShaderModule;
160 Move<VkShaderModule> m_teseShaderModule;
161 Move<VkShaderModule> m_geomShaderModule;
162 Move<VkShaderModule> m_fragShaderModule;
163
164 Move<VkPipelineLayout> m_pipelineLayout;
165 Move<VkPipeline> m_graphicsPipeline;
166
167 Move<VkCommandPool> m_cmdPool;
168 Move<VkCommandBuffer> m_cmdBuffer;
169 };
170
InterfaceMatchingTestInstance(Context & context,const TestParamsSp params)171 InterfaceMatchingTestInstance::InterfaceMatchingTestInstance(Context& context, const TestParamsSp params)
172 : vkt::TestInstance(context)
173 , m_params(params)
174 , m_alloc(context.getDeviceInterface(), context.getDevice(),
175 getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()))
176 {
177 }
178
iterate(void)179 tcu::TestStatus InterfaceMatchingTestInstance::iterate(void)
180 {
181 const DeviceInterface& vk = m_context.getDeviceInterface();
182 const VkDevice device = m_context.getDevice();
183 const VkQueue queue = m_context.getUniversalQueue();
184 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
185 const VkComponentMapping componentMappingRGBA = makeComponentMappingRGBA();
186 VkImageSubresourceRange subresourceRange { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u };
187 const VkFormat colorFormat (VK_FORMAT_R8G8B8A8_UNORM);
188 const tcu::UVec2 renderSize (16, 16);
189 const tcu::TextureFormat textureFormat = mapVkFormat(colorFormat);
190 const VkDeviceSize pixelDataSize = renderSize.x() * renderSize.y() * textureFormat.getPixelSize();
191 const VkDeviceSize vertexBufferOffset = 0;
192
193 // create color image that is used as a color attachment
194 {
195 const VkImageCreateInfo colorImageParams
196 {
197 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
198 DE_NULL, // const void* pNext;
199 0u, // VkImageCreateFlags flags;
200 VK_IMAGE_TYPE_2D, // VkImageType imageType;
201 colorFormat, // VkFormat format;
202 { renderSize.x(), renderSize.y(), 1u }, // VkExtent3D extent;
203 1u, // deUint32 mipLevels;
204 1u, // deUint32 arrayLayers;
205 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
206 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
207 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage;
208 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
209 1u, // deUint32 queueFamilyIndexCount;
210 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
211 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
212 };
213
214 m_colorImage = createImage(vk, device, &colorImageParams);
215
216 // allocate and bind color image memory
217 m_colorImageAlloc = m_alloc.allocate(getImageMemoryRequirements(vk, device, *m_colorImage), MemoryRequirement::Any);
218 VK_CHECK(vk.bindImageMemory(device, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset()));
219 }
220
221 // create color attachment view
222 {
223 const VkImageViewCreateInfo colorAttachmentViewParams
224 {
225 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
226 DE_NULL, // const void* pNext;
227 0u, // VkImageViewCreateFlags flags;
228 *m_colorImage, // VkImage image;
229 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
230 colorFormat, // VkFormat format;
231 componentMappingRGBA, // VkComponentMapping components;
232 subresourceRange // VkImageSubresourceRange subresourceRange;
233 };
234
235 m_colorAttachmentView = createImageView(vk, device, &colorAttachmentViewParams);
236 }
237
238 // create render pass
239 m_renderPass = makeRenderPass(vk, device, colorFormat);
240
241 // create framebuffer
242 {
243 const VkFramebufferCreateInfo framebufferParams
244 {
245 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
246 DE_NULL, // const void* pNext;
247 0u, // VkFramebufferCreateFlags flags;
248 *m_renderPass, // VkRenderPass renderPass;
249 1u, // deUint32 attachmentCount;
250 &m_colorAttachmentView.get(), // const VkImageView* pAttachments;
251 (deUint32)renderSize.x(), // deUint32 width;
252 (deUint32)renderSize.y(), // deUint32 height;
253 1u // deUint32 layers;
254 };
255
256 m_framebuffer = createFramebuffer(vk, device, &framebufferParams);
257 }
258
259 // create pipeline layout
260 {
261 const VkPipelineLayoutCreateInfo pipelineLayoutParams
262 {
263 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
264 DE_NULL, // const void* pNext;
265 0u, // VkPipelineLayoutCreateFlags flags;
266 0u, // deUint32 setLayoutCount;
267 DE_NULL, // const VkDescriptorSetLayout* pSetLayouts;
268 0u, // deUint32 pushConstantRangeCount;
269 DE_NULL // const VkPushConstantRange* pPushConstantRanges;
270 };
271
272 m_pipelineLayout = createPipelineLayout(vk, device, &pipelineLayoutParams);
273 }
274
275 // create pipeline
276 bool useTess = isPipelineOneOf(m_params->pipelineType, {
277 PipelineType::VERT_OUT_TESC_IN_TESE_FRAG,
278 PipelineType::VERT_TESC_TESE_OUT_FRAG_IN,
279 PipelineType::VERT_TESC_OUT_TESE_IN_FRAG,
280 PipelineType::VERT_OUT_TESC_IN_TESE_GEOM_FRAG,
281 PipelineType::VERT_TESC_TESE_OUT_GEOM_IN_FRAG,
282 PipelineType::VERT_TESC_TESE_GEOM_OUT_FRAG_IN });
283
284 m_vertShaderModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0);
285 m_fragShaderModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0);
286 if (useTess)
287 {
288 m_tescShaderModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("tesc"), 0);
289 m_teseShaderModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("tese"), 0);
290 }
291
292 if (isPipelineOneOf(m_params->pipelineType, {
293 PipelineType::VERT_OUT_GEOM_IN_FRAG,
294 PipelineType::VERT_GEOM_OUT_FRAG_IN,
295 PipelineType::VERT_OUT_TESC_IN_TESE_GEOM_FRAG,
296 PipelineType::VERT_TESC_TESE_OUT_GEOM_IN_FRAG,
297 PipelineType::VERT_TESC_TESE_GEOM_OUT_FRAG_IN }))
298 {
299 m_geomShaderModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("geom"), 0);
300 }
301 m_graphicsPipeline = makeGraphicsPipeline(
302 vk, // DeviceInterface& vk
303 device, // VkDevice device
304 *m_pipelineLayout, // VkPipelineLayout pipelineLayout
305 *m_vertShaderModule, // VkShaderModule vertexShaderModule
306 *m_tescShaderModule, // VkShaderModule tessellationControlModule
307 *m_teseShaderModule, // VkShaderModule tessellationEvalModule
308 *m_geomShaderModule, // VkShaderModule geometryShaderModule
309 *m_fragShaderModule, // VkShaderModule fragmentShaderModule
310 *m_renderPass, // VkRenderPass renderPass
311 { makeViewport(renderSize) }, // std::vector<VkViewport>& viewports
312 { makeRect2D(renderSize) }, // std::vector<VkRect2D>& scissors
313 useTess ? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST : VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, // VkPrimitiveTopology topology
314 0u, // const deUint32 subpass
315 useTess ? 1u : 0u); // const deUint32 patchControlPoints
316
317 // create vertex buffer
318 {
319 std::vector<float> vertices
320 {
321 1.0f, -1.0f, 0.0f, 1.0f,
322 -1.0f, 1.0f, 0.0f, 1.0f,
323 -1.0f, -1.0f, 0.0f, 1.0f,
324 };
325 const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(vertices.size() * sizeof(float), VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
326
327 m_vertexBuffer = createBuffer(vk, device, &bufferCreateInfo);
328 m_vertexBufferAlloc = m_alloc.allocate(getBufferMemoryRequirements(vk, device, *m_vertexBuffer), MemoryRequirement::HostVisible);
329 VK_CHECK(vk.bindBufferMemory(device, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));
330
331 deMemcpy(m_vertexBufferAlloc->getHostPtr(), vertices.data(), vertices.size() * sizeof(float));
332 flushAlloc(vk, device, *m_vertexBufferAlloc);
333 }
334
335 // create buffer to which we will grab rendered result
336 {
337 const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(pixelDataSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
338
339 m_resultBuffer = createBuffer(vk, device, &bufferCreateInfo);
340 m_resultBufferAlloc = m_alloc.allocate(getBufferMemoryRequirements(vk, device, *m_resultBuffer), MemoryRequirement::HostVisible);
341 VK_CHECK(vk.bindBufferMemory(device, *m_resultBuffer, m_resultBufferAlloc->getMemory(), m_resultBufferAlloc->getOffset()));
342 }
343
344 // create command pool and command buffer
345 m_cmdPool = createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
346 m_cmdBuffer = allocateCommandBuffer(vk, device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
347
348 // record command buffer
349 beginCommandBuffer(vk, *m_cmdBuffer, 0u);
350
351 // change image layout so we can use it as color attachment
352 const VkImageMemoryBarrier attachmentLayoutBarrier = makeImageMemoryBarrier(
353 VK_ACCESS_NONE_KHR, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
354 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
355 *m_colorImage, subresourceRange);
356 vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
357 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &attachmentLayoutBarrier);
358
359 // render single triangle
360 beginRenderPass(vk, *m_cmdBuffer, *m_renderPass, *m_framebuffer, makeRect2D(renderSize), Vec4(0.0f, 0.0f, 0.0f, 1.0f));
361
362 vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipeline);
363 vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &*m_vertexBuffer, &vertexBufferOffset);
364 vk.cmdDraw(*m_cmdBuffer, 4, 1, 0, 0);
365
366 endRenderPass(vk, *m_cmdBuffer);
367
368 copyImageToBuffer(vk, *m_cmdBuffer, *m_colorImage, *m_resultBuffer, tcu::IVec2(renderSize.x(), renderSize.y()));
369
370 endCommandBuffer(vk, *m_cmdBuffer);
371
372 // submit commands
373 submitCommandsAndWait(vk, device, queue, *m_cmdBuffer);
374
375 // read buffer data
376 invalidateAlloc(vk, device, *m_resultBufferAlloc);
377
378 // validate result - verification is done in glsl, just checking
379 // two texels, if test passed then r channel should be set to 255
380 const unsigned char* bufferPtr = static_cast<unsigned char*>(m_resultBufferAlloc->getHostPtr());
381 if ((bufferPtr[0] > 254) && (bufferPtr[renderSize.x()*4+8] > 254))
382 return TestStatus::pass("Pass");
383
384 const tcu::ConstPixelBufferAccess resultAccess(textureFormat, tcu::IVec3((int)renderSize.x(), (int)renderSize.y(), 1u), bufferPtr);
385 TestLog& log = m_context.getTestContext().getLog();
386 log << tcu::TestLog::ImageSet("Result of rendering", "")
387 << TestLog::Image("Result", "", resultAccess)
388 << tcu::TestLog::EndImageSet;
389
390 return TestStatus::fail("Fail");
391 }
392
393 class InterfaceMatchingTestCase : public vkt::TestCase
394 {
395 public:
396 InterfaceMatchingTestCase (tcu::TestContext& testContext,
397 TestParamsSp params);
398 virtual ~InterfaceMatchingTestCase (void) = default;
399
400 void initPrograms (SourceCollections& sourceCollections) const override;
401 void checkSupport (Context& context) const override;
402 TestInstance* createInstance (Context& context) const override;
403
404 protected:
405
406 enum class ComponentType
407 {
408 FLOAT = 0,
409 INT,
410 UINT
411 };
412
413 struct VecData
414 {
415 std::string glslType;
416 ComponentType componentType;
417 deUint32 componentsCount;
418 std::string components[4];
419 };
420
421 struct DecorationData
422 {
423 std::string namePart;
424 std::string glslDecoration;
425 std::string glslComponent;
426 };
427
428 // helper structure used during construction of in/out declaration
429 struct PipelineData
430 {
431 bool outDeclArray;
432 bool inFlatDecoration; // needed for frag in
433 bool inDeclArray;
434 };
435
436 typedef std::map<std::string, std::string> SpecializationMap;
437
438 std::string genOutAssignment (const std::string& variableName, const VecData& outVecData) const;
439 std::string genInVerification (const std::string& variableName, const VecData& outVecData, const VecData& inVecData) const;
440
441 const VecData& getVecData (VecType vecType) const;
442 const DecorationData& getDecorationData (DecorationType decorationType) const;
443
444 const PipelineData& getPipelineData (PipelineType pipelineType) const;
445 std::string generateName (const TestParams& testParams) const;
446
447 private:
448
449 const TestParamsSp m_params;
450 };
451
InterfaceMatchingTestCase(tcu::TestContext & testContext,TestParamsSp params)452 InterfaceMatchingTestCase::InterfaceMatchingTestCase(tcu::TestContext& testContext,
453 TestParamsSp params)
454 : vkt::TestCase (testContext, generateName(*params), "")
455 , m_params (params)
456 {
457 }
458
initPrograms(SourceCollections & sourceCollections) const459 void InterfaceMatchingTestCase::initPrograms(SourceCollections& sourceCollections) const
460 {
461 GlslSourceCollection& glslSources = sourceCollections.glslSources;
462 const VecData& outVecData = getVecData(m_params->outVecType);
463 const VecData& inVecData = getVecData(m_params->inVecType);
464 const DecorationData& outDecorationData = getDecorationData(m_params->outDeclDecoration);
465 const DecorationData& inDecorationData = getDecorationData(m_params->inDeclDecoration);
466 const PipelineData& pipelineData = getPipelineData(m_params->pipelineType);
467
468 // deterimine if decoration or array is needed for in/out declarations
469 const std::string outDeclArray = pipelineData.outDeclArray ? "[]" : "";
470 const std::string inDeclArray = pipelineData.inDeclArray ? "[]" : "";
471 const std::string variableToAssignArray = pipelineData.outDeclArray ? "[gl_InvocationID]" : "";
472 const std::string variableToVerifyArray = pipelineData.inDeclArray ? "[0]" : "";
473
474 std::string outDecoration = "";
475 std::string inDecoration = pipelineData.inFlatDecoration ? "flat " : "";
476 std::string outComponent = outDecorationData.glslComponent;
477 std::string inComponent = inDecorationData.glslComponent;
478 if (m_params->testType == TestType::DECORATION_MISMATCH)
479 {
480 outDecoration = outDecorationData.glslDecoration;
481 inDecoration = inDecorationData.glslDecoration;
482 }
483
484 std::string outDeclaration;
485 std::string inDeclaration;
486 std::string variableToAssignName;
487 std::string variableToVerifyName;
488
489 // generate in/out declarations
490 switch (m_params->definitionType)
491 {
492 case DefinitionType::LOOSE_VARIABLE:
493 outDeclaration = "layout(location = 0" + outDecorationData.glslComponent + ") out " + outDecoration + outVecData.glslType + " looseVariable" + outDeclArray + ";\n";
494 inDeclaration = "layout(location = 0" + inDecorationData.glslComponent + ") in " + inDecoration + inVecData.glslType + " looseVariable" + inDeclArray + ";\n";
495 variableToAssignName = "looseVariable" + variableToAssignArray;
496 variableToVerifyName = "looseVariable" + variableToVerifyArray;
497 break;
498
499 case DefinitionType::MEMBER_OF_BLOCK:
500 outDeclaration += "layout(location = 0) out block {\n"
501 " vec2 dummy;\n"
502 "layout(location = 1" + outDecorationData.glslComponent + ") " +
503 outDecoration + outVecData.glslType + " variableInBlock;\n"
504 "} testBlock" + outDeclArray + ";\n";
505 inDeclaration += "in block {\n"
506 "layout(location = 0) vec2 dummy;\n"
507 "layout(location = 1" + inDecorationData.glslComponent + ") " +
508 inDecoration + inVecData.glslType + " variableInBlock;\n"
509 "} testBlock" + inDeclArray + ";\n";
510 variableToAssignName = "testBlock" + variableToAssignArray + ".variableInBlock";
511 variableToVerifyName = "testBlock" + variableToVerifyArray + ".variableInBlock";
512 break;
513
514 case DefinitionType::MEMBER_OF_STRUCTURE:
515 outDeclaration += "layout(location = 0) out " + outDecoration + "struct {\n"
516 " vec2 dummy;\n"
517 " " + outVecData.glslType + " variableInStruct;\n"
518 "} testStruct" + outDeclArray + ";\n";
519 inDeclaration += "layout(location = 0) in " + inDecoration + "struct {\n"
520 " vec2 dummy;\n"
521 " " + inVecData.glslType + " variableInStruct;\n"
522 "} testStruct" + inDeclArray + ";\n";
523 variableToAssignName = "testStruct" + variableToAssignArray + ".variableInStruct";
524 variableToVerifyName = "testStruct" + variableToVerifyArray + ".variableInStruct";
525 break;
526
527 case DefinitionType::MEMBER_OF_ARRAY_OF_STRUCTURES:
528 outDeclaration += "layout(location = 0) out " + outDecoration + "struct {\n"
529 " float dummy;\n"
530 " " + outVecData.glslType + " variableInStruct;\n"
531 "} testStructArray" + outDeclArray + "[3];\n";
532 inDeclaration += "layout(location = 0) in " + inDecoration + "struct {\n"
533 " float dummy;\n"
534 " " + inVecData.glslType + " variableInStruct;\n"
535 "} testStructArray" + inDeclArray + "[3];\n";
536 // just verify last item from array
537 variableToAssignName = "testStructArray" + variableToAssignArray + "[2].variableInStruct";
538 variableToVerifyName = "testStructArray" + variableToVerifyArray + "[2].variableInStruct";
539 break;
540
541 case DefinitionType::MEMBER_OF_STRUCTURE_IN_BLOCK:
542 outDeclaration += "struct TestStruct {\n"
543 " vec2 dummy;\n"
544 " " + outVecData.glslType + " variableInStruct;\n"
545 "};\n"
546 "layout(location = 0) out block {\n"
547 " vec2 dummy;\n"
548 " " + outDecoration + "TestStruct structInBlock;\n"
549 "} testBlock" + outDeclArray + ";\n";
550 inDeclaration += "struct TestStruct {\n"
551 " vec2 dummy;\n"
552 " " + inVecData.glslType + " variableInStruct;\n"
553 "};\n"
554 "layout(location = 0) in block {\n"
555 " vec2 dummy;\n"
556 " " + inDecoration + "TestStruct structInBlock;\n"
557 "} testBlock" + inDeclArray + ";\n";
558 variableToAssignName = "testBlock" + variableToAssignArray + ".structInBlock.variableInStruct";
559 variableToVerifyName = "testBlock" + variableToVerifyArray + ".structInBlock.variableInStruct";
560 break;
561
562 case DefinitionType::MEMBER_OF_ARRAY_OF_STRUCTURES_IN_BLOCK:
563 outDeclaration += "struct TestStruct {\n"
564 " vec4 dummy;\n"
565 " " + outVecData.glslType + " variableInStruct;\n"
566 "};\n"
567 "layout(location = 0) out block {\n"
568 " " + outDecoration + "TestStruct structArrayInBlock[3];\n"
569 "} testBlock" + outDeclArray + ";\n";
570 inDeclaration += "struct TestStruct {\n"
571 " vec4 dummy;\n"
572 " " + inVecData.glslType + " variableInStruct;\n"
573 "};"
574 "layout(location = 0) in block {\n"
575 " " + inDecoration + "TestStruct structArrayInBlock[3];\n"
576 "} testBlock" + inDeclArray + ";\n";
577 // just verify second item from array
578 variableToAssignName = "testBlock" + variableToAssignArray + ".structArrayInBlock[1].variableInStruct";
579 variableToVerifyName = "testBlock" + variableToVerifyArray + ".structArrayInBlock[1].variableInStruct";
580 break;
581
582 default:
583 DE_ASSERT(DE_FALSE);
584 }
585
586 std::string outValueAssignment = genOutAssignment (variableToAssignName, outVecData);
587 std::string inValueVerification = genInVerification(variableToVerifyName, outVecData, inVecData);
588
589 // create specialization map and grab references to both
590 // values so we dont have to index into it in every case
591 SpecializationMap specializationMap
592 {
593 { "DECLARATIONS", "" },
594 { "OPERATIONS", "" },
595 };
596 std::string& declarations = specializationMap["DECLARATIONS"];
597 std::string& operations = specializationMap["OPERATIONS"];
598
599 // define vertex shader source
600 if (isPipelineOneOf(m_params->pipelineType, {
601 PipelineType::VERT_OUT_FRAG_IN,
602 PipelineType::VERT_OUT_TESC_IN_TESE_FRAG,
603 PipelineType::VERT_OUT_GEOM_IN_FRAG,
604 PipelineType::VERT_OUT_TESC_IN_TESE_GEOM_FRAG }))
605 {
606 declarations = outDeclaration;
607 operations = outValueAssignment;
608 }
609 // else passthrough source
610
611 tcu::StringTemplate vertTemplate(
612 "#version 450\n"
613 "layout(location = 0) in vec4 inPosition;\n"
614 "${DECLARATIONS}"
615 "void main(void)\n"
616 "{\n"
617 " gl_Position = inPosition;\n"
618 "${OPERATIONS}"
619 "}\n");
620 glslSources.add("vert") << glu::VertexSource(vertTemplate.specialize(specializationMap));
621
622 // define tesselation control shader source
623 bool tescNeeded = DE_FALSE;
624 switch (m_params->pipelineType)
625 {
626 case PipelineType::VERT_TESC_OUT_TESE_IN_FRAG:
627 declarations = outDeclaration;
628 operations = outValueAssignment;
629 tescNeeded = DE_TRUE;
630 break;
631
632 case PipelineType::VERT_OUT_TESC_IN_TESE_FRAG:
633 case PipelineType::VERT_OUT_TESC_IN_TESE_GEOM_FRAG:
634 declarations = inDeclaration +
635 "layout(location = 0) out float outResult[];\n";
636 operations = " float result;\n" +
637 inValueVerification +
638 " outResult[gl_InvocationID] = result;\n";
639 tescNeeded = DE_TRUE;
640 break;
641
642 case PipelineType::VERT_TESC_TESE_OUT_FRAG_IN:
643 case PipelineType::VERT_TESC_TESE_OUT_GEOM_IN_FRAG:
644 case PipelineType::VERT_TESC_TESE_GEOM_OUT_FRAG_IN:
645 // passthrough sources
646 tescNeeded = DE_TRUE;
647 break;
648
649 default:
650 break;
651 }
652
653 std::string tescSource = tescNeeded ?
654 StringTemplate(
655 "#version 450\n"
656 "#extension GL_EXT_tessellation_shader : require\n\n"
657 "layout(vertices = 1) out;\n\n"
658 "${DECLARATIONS}"
659 "void main(void)\n"
660 "{\n"
661 " gl_TessLevelInner[0] = 1.0;\n"
662 " gl_TessLevelOuter[0] = 1.0;\n"
663 " gl_TessLevelOuter[1] = 1.0;\n"
664 " gl_TessLevelOuter[2] = 1.0;\n"
665 "${OPERATIONS}"
666 "}\n").specialize(specializationMap)
667 : "";
668
669 // define tesselation evaluation shader source
670 bool teseNeeded = DE_FALSE;
671 switch (m_params->pipelineType)
672 {
673 case PipelineType::VERT_TESC_TESE_OUT_FRAG_IN:
674 case PipelineType::VERT_TESC_TESE_OUT_GEOM_IN_FRAG:
675 declarations = outDeclaration;
676 operations = outValueAssignment;
677 teseNeeded = DE_TRUE;
678 break;
679
680 case PipelineType::VERT_TESC_OUT_TESE_IN_FRAG:
681 declarations = inDeclaration +
682 "layout(location = 0) out float outResult;\n";
683 operations = " float result;\n" +
684 inValueVerification +
685 " outResult = result;\n";
686 teseNeeded = DE_TRUE;
687 break;
688
689 case PipelineType::VERT_OUT_TESC_IN_TESE_FRAG:
690 case PipelineType::VERT_OUT_TESC_IN_TESE_GEOM_FRAG:
691 declarations = "layout(location = 0) in float inResult[];\n"
692 "layout(location = 0) out float outResult;\n";
693 operations = " outResult = inResult[0];\n";
694 teseNeeded = DE_TRUE;
695 break;
696
697 case PipelineType::VERT_TESC_TESE_GEOM_OUT_FRAG_IN:
698 // passthrough sources
699 teseNeeded = DE_TRUE;
700 break;
701
702 default:
703 break;
704 }
705
706 std::string teseSource = teseNeeded ?
707 StringTemplate(
708 "#version 450\n"
709 "#extension GL_EXT_tessellation_shader : require\n\n"
710 "layout(triangles) in;\n"
711 "${DECLARATIONS}"
712 "void main(void)\n"
713 "{\n"
714 " gl_Position = vec4(gl_TessCoord.xy * 2.0 - 1.0, 0.0, 1.0);\n"
715 "${OPERATIONS}"
716 "}\n").specialize(specializationMap)
717 : "";
718
719 DE_ASSERT(tescSource.empty() == teseSource.empty());
720 if (!tescSource.empty())
721 {
722 glslSources.add("tesc") << glu::TessellationControlSource(tescSource);
723 glslSources.add("tese") << glu::TessellationEvaluationSource(teseSource);
724 }
725
726 // define geometry shader source
727 bool geomNeeded = DE_FALSE;
728 switch (m_params->pipelineType)
729 {
730 case PipelineType::VERT_GEOM_OUT_FRAG_IN:
731 case PipelineType::VERT_TESC_TESE_GEOM_OUT_FRAG_IN:
732 declarations = outDeclaration;
733 operations = outValueAssignment;
734 geomNeeded = DE_TRUE;
735 break;
736
737 case PipelineType::VERT_OUT_GEOM_IN_FRAG:
738 case PipelineType::VERT_TESC_TESE_OUT_GEOM_IN_FRAG:
739 declarations = inDeclaration +
740 "layout(location = 0) out float result;\n";
741 operations = inValueVerification;
742 geomNeeded = DE_TRUE;
743 break;
744
745 case PipelineType::VERT_OUT_TESC_IN_TESE_GEOM_FRAG:
746 declarations = "layout(location = 0) in float inResult[];\n"
747 "layout(location = 0) out float outResult;\n";
748 operations = " outResult = inResult[0];\n";
749 geomNeeded = DE_TRUE;
750 break;
751
752 default:
753 break;
754 }
755
756 if (geomNeeded)
757 {
758 tcu::StringTemplate geomTemplate(
759 "#version 450\n"
760 "#extension GL_EXT_geometry_shader : require\n"
761 "layout(triangles) in;\n"
762 "layout(triangle_strip, max_vertices=3) out;\n"
763 "${DECLARATIONS}"
764 "void main(void)\n"
765 "{\n"
766 "${OPERATIONS}"
767 " gl_Position = vec4( 1.0, -1.0, 0.0, 1.0);\n"
768 " EmitVertex();\n"
769 "${OPERATIONS}"
770 " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
771 " EmitVertex();\n"
772 "${OPERATIONS}"
773 " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
774 " EmitVertex();\n"
775 " EndPrimitive();\n"
776 "}\n");
777 glslSources.add("geom") << glu::GeometrySource(geomTemplate.specialize(specializationMap));
778 }
779
780 // define fragment shader source
781 if (isPipelineOneOf(m_params->pipelineType, {
782 PipelineType::VERT_OUT_FRAG_IN,
783 PipelineType::VERT_TESC_TESE_OUT_FRAG_IN,
784 PipelineType::VERT_GEOM_OUT_FRAG_IN,
785 PipelineType::VERT_TESC_TESE_GEOM_OUT_FRAG_IN }))
786 {
787 declarations = inDeclaration;
788 operations = " float result = 0.0;\n" +
789 inValueVerification;
790 }
791 else // passthrough source
792 {
793 declarations = "layout(location = 0) in flat float result;\n";
794 operations = "";
795 }
796
797 tcu::StringTemplate fragTemplate(
798 "#version 450\n"
799 "layout(location = 0) out vec4 fragColor;\n"
800 "${DECLARATIONS}"
801 "void main(void)\n"
802 "{\n"
803 "${OPERATIONS}"
804 " fragColor = vec4(result);\n"
805 "}\n");
806 glslSources.add("frag") << glu::FragmentSource(fragTemplate.specialize(specializationMap));
807 }
808
genOutAssignment(const std::string & variableName,const VecData & outVecData) const809 std::string InterfaceMatchingTestCase::genOutAssignment(const std::string& variableName, const VecData& outVecData) const
810 {
811 // generate value assignment to out variable;
812 // for vec2/looseVariable this will generate:
813 // "looseVariable = vec2(-2.0, 3.0);"
814
815 // define separators to avoid if statements in loop
816 std::string outSeparator(", ");
817 std::string endSeparator("");
818 std::vector<std::string*> outSeparators(4, &outSeparator);
819 outSeparators[outVecData.componentsCount - 1] = &endSeparator;
820
821 // generate value assignment
822 std::string outValueAssignment = std::string(" ") + variableName + " = " + outVecData.glslType + "(";
823 for (deUint32 i = 0; i < outVecData.componentsCount; ++i)
824 outValueAssignment += outVecData.components[i] + *outSeparators[i];
825
826 return outValueAssignment + ");\n";
827 }
828
genInVerification(const std::string & variableName,const VecData & outVecData,const VecData & inVecData) const829 std::string InterfaceMatchingTestCase::genInVerification(const std::string& variableName, const VecData& outVecData, const VecData& inVecData) const
830 {
831 // generate value verification;
832 // note that input has same or less components then output;
833 // for vec2/looseVariable this will generate:
834 // "result = float(abs(looseVariable.x - -2.0) < eps) *"
835 // "float(abs(looseVariable.y - 3.0) < eps);\n"
836
837 static const std::string componentNames[] = { "x", "y", "z", "w" };
838
839 // define separators to avoid if statements in loop
840 std::string inSeparator (" *\n\t\t ");
841 std::string endSeparator ("");
842 std::string* inSeparators[] { &inSeparator, &inSeparator, &inSeparator, &endSeparator };
843
844 inSeparators[inVecData.componentsCount - 1] = &endSeparator;
845
846 std::string inValueVerification(" result = ");
847 tcu::StringTemplate verificationTemplate(
848 inVecData.componentType == ComponentType::FLOAT ?
849 "float(abs(" + variableName + ".${COMPONENT} - ${VALUE}) < 0.001)" :
850 "float(" + variableName + ".${COMPONENT} == ${VALUE})");
851
852 // verify each component using formula for float or int
853 for (deUint32 i = 0; i < inVecData.componentsCount; ++i)
854 {
855 inValueVerification += verificationTemplate.specialize({
856 { "COMPONENT", componentNames[i] },
857 { "VALUE", outVecData.components[i] }
858 });
859 inValueVerification += *inSeparators[i];
860 }
861
862 return inValueVerification + ";\n";
863 }
864
checkSupport(Context & context) const865 void InterfaceMatchingTestCase::checkSupport(Context& context) const
866 {
867 // when outputs from earlier stage are matched with smaller
868 // inputs in future stage request VK_KHR_maintenance4
869 if ((m_params->testType == TestType::VECTOR_LENGTH) &&
870 (m_params->outVecType != m_params->inVecType))
871 {
872 context.requireDeviceFunctionality("VK_KHR_maintenance4");
873 }
874
875 const InstanceInterface& vki = context.getInstanceInterface();
876 const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
877 const VkPhysicalDeviceFeatures features = getPhysicalDeviceFeatures(vki, physicalDevice);
878
879 if (isPipelineOneOf(m_params->pipelineType, {
880 PipelineType::VERT_OUT_TESC_IN_TESE_FRAG,
881 PipelineType::VERT_TESC_TESE_OUT_FRAG_IN,
882 PipelineType::VERT_TESC_OUT_TESE_IN_FRAG,
883 PipelineType::VERT_OUT_TESC_IN_TESE_GEOM_FRAG,
884 PipelineType::VERT_TESC_TESE_OUT_GEOM_IN_FRAG,
885 PipelineType::VERT_TESC_TESE_GEOM_OUT_FRAG_IN }))
886 if (!features.tessellationShader)
887 TCU_THROW(NotSupportedError, "Tessellation shader not supported");
888
889 if (isPipelineOneOf(m_params->pipelineType, {
890 PipelineType::VERT_OUT_GEOM_IN_FRAG,
891 PipelineType::VERT_GEOM_OUT_FRAG_IN,
892 PipelineType::VERT_OUT_TESC_IN_TESE_GEOM_FRAG,
893 PipelineType::VERT_TESC_TESE_OUT_GEOM_IN_FRAG,
894 PipelineType::VERT_TESC_TESE_GEOM_OUT_FRAG_IN }))
895 if (!features.geometryShader)
896 TCU_THROW(NotSupportedError, "Geometry shader not supported");
897 }
898
createInstance(Context & context) const899 TestInstance* InterfaceMatchingTestCase::createInstance(Context& context) const
900 {
901 return new InterfaceMatchingTestInstance(context, m_params);
902 }
903
getVecData(VecType vecType) const904 const InterfaceMatchingTestCase::VecData& InterfaceMatchingTestCase::getVecData(VecType vecType) const
905 {
906 static const std::map<VecType, VecData> vecDataMap
907 {
908 { VecType::VEC2, { "vec2", ComponentType::FLOAT, 2, { "-2.0", "3.0", "", "" } } },
909 { VecType::VEC3, { "vec3", ComponentType::FLOAT, 3, { "-3.0", "2.0", "5.0", "" } } },
910 { VecType::VEC4, { "vec4", ComponentType::FLOAT, 4, { "-4.0", "-9.0", "3.0", "7.0" } } },
911 { VecType::IVEC2, { "ivec2", ComponentType::INT, 2, { "-4", "8", "", "" } } },
912 { VecType::IVEC3, { "ivec3", ComponentType::INT, 3, { "-5", "10", "15", "" } } },
913 { VecType::IVEC4, { "ivec4", ComponentType::INT, 4, { "-16", "12", "20", "80" } } },
914 { VecType::UVEC2, { "uvec2", ComponentType::UINT, 2, { "2", "8", "", "" } } },
915 { VecType::UVEC3, { "uvec3", ComponentType::UINT, 3, { "3", "9", "27", "" } } },
916 { VecType::UVEC4, { "uvec4", ComponentType::UINT, 4, { "4", "16", "64", "256" } } },
917 };
918
919 DE_ASSERT(vecDataMap.find(vecType) != vecDataMap.end());
920 return vecDataMap.at(vecType);
921 }
922
getDecorationData(DecorationType decorationType) const923 const InterfaceMatchingTestCase::DecorationData& InterfaceMatchingTestCase::getDecorationData(DecorationType decorationType) const
924 {
925 static const std::map<DecorationType, DecorationData> decorationDataMap
926 {
927 { DecorationType::NONE, { "none", "", "" } },
928 { DecorationType::FLAT, { "flat", "flat ", "" } },
929 { DecorationType::NO_PERSPECTIVE, { "noperspective", "noperspective ", "" } },
930 { DecorationType::COMPONENT0, { "component0", "", ", component = 0 " } },
931 };
932
933 DE_ASSERT(decorationDataMap.find(decorationType) != decorationDataMap.end());
934 return decorationDataMap.at(decorationType);
935 }
936
getPipelineData(PipelineType pipelineType) const937 const InterfaceMatchingTestCase::PipelineData& InterfaceMatchingTestCase::getPipelineData(PipelineType pipelineType) const
938 {
939 // pipelineDataMap is used to simplify generation of declarations in glsl
940 // it represent fallowing rules:
941 // * for case where tesc outputs variable it must be declarred as an array
942 // * when frag input variable is verified we need to use flat interpolation
943 // * all stages except for frag need input to be array (note: we do not use input in vert)
944
945 static const std::map<PipelineType, PipelineData> pipelineDataMap
946 {
947 // outArr inFlat inArr
948 { PipelineType::VERT_OUT_FRAG_IN, { 0, 1, 0 } },
949 { PipelineType::VERT_OUT_TESC_IN_TESE_FRAG, { 0, 0, 1 } },
950 { PipelineType::VERT_TESC_TESE_OUT_FRAG_IN, { 0, 1, 0 } },
951 { PipelineType::VERT_TESC_OUT_TESE_IN_FRAG, { 1, 0, 1 } },
952 { PipelineType::VERT_OUT_GEOM_IN_FRAG, { 0, 0, 1 } },
953 { PipelineType::VERT_GEOM_OUT_FRAG_IN, { 0, 1, 0 } },
954 { PipelineType::VERT_OUT_TESC_IN_TESE_GEOM_FRAG, { 0, 0, 1 } },
955 { PipelineType::VERT_TESC_TESE_OUT_GEOM_IN_FRAG, { 0, 0, 1 } },
956 { PipelineType::VERT_TESC_TESE_GEOM_OUT_FRAG_IN, { 0, 1, 0 } },
957 };
958
959 DE_ASSERT(pipelineDataMap.find(pipelineType) != pipelineDataMap.end());
960 return pipelineDataMap.at(pipelineType);
961 }
962
generateName(const TestParams & testParams) const963 std::string InterfaceMatchingTestCase::generateName(const TestParams& testParams) const
964 {
965 static const std::map<PipelineType, std::string> pipelineTypeMap
966 {
967 { PipelineType::VERT_OUT_FRAG_IN, "vert_out_frag_in" },
968 { PipelineType::VERT_OUT_TESC_IN_TESE_FRAG, "vert_out_tesc_in_tese_frag" },
969 { PipelineType::VERT_TESC_TESE_OUT_FRAG_IN, "vert_tesc_tese_out_frag_in" },
970 { PipelineType::VERT_TESC_OUT_TESE_IN_FRAG, "vert_tesc_out_tese_in_frag" },
971 { PipelineType::VERT_OUT_GEOM_IN_FRAG, "vert_out_geom_in_frag" },
972 { PipelineType::VERT_GEOM_OUT_FRAG_IN, "vert_geom_out_frag_in" },
973 { PipelineType::VERT_OUT_TESC_IN_TESE_GEOM_FRAG, "vert_out_tesc_in_tese_geom_frag" },
974 { PipelineType::VERT_TESC_TESE_OUT_GEOM_IN_FRAG, "vert_tesc_tese_out_geom_in_frag" },
975 { PipelineType::VERT_TESC_TESE_GEOM_OUT_FRAG_IN, "vert_tesc_tese_geom_out_frag_in" },
976 };
977
978 static const std::map <DefinitionType, std::string> definitionTypeMap
979 {
980 { DefinitionType::LOOSE_VARIABLE, "loose_variable" },
981 { DefinitionType::MEMBER_OF_BLOCK, "member_of_block" },
982 { DefinitionType::MEMBER_OF_STRUCTURE, "member_of_structure" },
983 { DefinitionType::MEMBER_OF_ARRAY_OF_STRUCTURES, "member_of_array_of_structures" },
984 { DefinitionType::MEMBER_OF_STRUCTURE_IN_BLOCK, "member_of_structure_in_block" },
985 { DefinitionType::MEMBER_OF_ARRAY_OF_STRUCTURES_IN_BLOCK, "member_of_array_of_structures_in_block" },
986 };
987
988 DE_ASSERT(pipelineTypeMap.find(testParams.pipelineType) != pipelineTypeMap.end());
989 DE_ASSERT(definitionTypeMap.find(testParams.definitionType) != definitionTypeMap.end());
990
991 std::string caseName;
992
993 if (testParams.testType == TestType::VECTOR_LENGTH)
994 caseName = "out_" + getVecData(testParams.outVecType).glslType +
995 "_in_" + getVecData(testParams.inVecType).glslType;
996 else
997 caseName = "out_" + getDecorationData(testParams.outDeclDecoration).namePart +
998 "_in_" + getDecorationData(testParams.inDeclDecoration).namePart;
999
1000 return caseName + "_" +
1001 definitionTypeMap.at(testParams.definitionType) + "_" +
1002 pipelineTypeMap.at(testParams.pipelineType);
1003 };
1004
1005 } // anonymous
1006
createInterfaceMatchingTests(tcu::TestContext & testCtx)1007 tcu::TestCaseGroup* createInterfaceMatchingTests(tcu::TestContext& testCtx)
1008 {
1009 VecType vecTypeList[3][3]
1010 {
1011 { VecType::VEC4, VecType::VEC3, VecType::VEC2 }, // float
1012 { VecType::IVEC4, VecType::IVEC3, VecType::IVEC2 }, // int
1013 { VecType::UVEC4, VecType::UVEC3, VecType::UVEC2 }, // uint
1014 };
1015
1016 PipelineType pipelineTypeList[]
1017 {
1018 PipelineType::VERT_OUT_FRAG_IN,
1019 PipelineType::VERT_OUT_TESC_IN_TESE_FRAG,
1020 PipelineType::VERT_TESC_TESE_OUT_FRAG_IN,
1021 PipelineType::VERT_TESC_OUT_TESE_IN_FRAG,
1022 PipelineType::VERT_OUT_GEOM_IN_FRAG,
1023 PipelineType::VERT_GEOM_OUT_FRAG_IN,
1024 PipelineType::VERT_OUT_TESC_IN_TESE_GEOM_FRAG,
1025 PipelineType::VERT_TESC_TESE_OUT_GEOM_IN_FRAG,
1026 PipelineType::VERT_TESC_TESE_GEOM_OUT_FRAG_IN,
1027 };
1028
1029 DefinitionType definitionsTypeList[]
1030 {
1031 DefinitionType::LOOSE_VARIABLE,
1032 DefinitionType::MEMBER_OF_BLOCK,
1033 DefinitionType::MEMBER_OF_STRUCTURE,
1034 DefinitionType::MEMBER_OF_ARRAY_OF_STRUCTURES,
1035 DefinitionType::MEMBER_OF_STRUCTURE_IN_BLOCK,
1036 DefinitionType::MEMBER_OF_ARRAY_OF_STRUCTURES_IN_BLOCK,
1037 };
1038
1039 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "interface_matching", ""));
1040
1041 de::MovePtr<tcu::TestCaseGroup> vectorMatching(new tcu::TestCaseGroup(testCtx, "vector_length", "Tests vector matching"));
1042 for (PipelineType pipelineType : pipelineTypeList)
1043 for (DefinitionType defType : definitionsTypeList)
1044 {
1045 // iterate over vector type - float, int or uint
1046 for (deUint32 vecDataFormat = 0; vecDataFormat < 3; ++vecDataFormat)
1047 {
1048 // iterate over all out/in lenght combinations
1049 const VecType* vecType = vecTypeList[vecDataFormat];
1050 for (deUint32 outVecSizeIndex = 0; outVecSizeIndex < 3; ++outVecSizeIndex)
1051 {
1052 VecType outVecType = vecType[outVecSizeIndex];
1053 for (deUint32 inVecSizeIndex = 0; inVecSizeIndex < 3; ++inVecSizeIndex)
1054 {
1055 VecType inVecType = vecType[inVecSizeIndex];
1056 if (outVecType < inVecType)
1057 continue;
1058
1059 auto testParams = new TestParams
1060 {
1061 TestType::VECTOR_LENGTH,
1062 outVecType,
1063 inVecType,
1064 DecorationType::NONE,
1065 DecorationType::NONE,
1066 pipelineType,
1067 defType
1068 };
1069
1070 vectorMatching->addChild(new InterfaceMatchingTestCase(testCtx, TestParamsSp(testParams)));
1071 }
1072 }
1073 }
1074 }
1075 testGroup->addChild(vectorMatching.release());
1076
1077 std::vector<std::pair<DecorationType, DecorationType> > decorationPairs
1078 {
1079 { DecorationType::NONE, DecorationType::NO_PERSPECTIVE },
1080 { DecorationType::NONE, DecorationType::FLAT },
1081 { DecorationType::FLAT, DecorationType::NO_PERSPECTIVE },
1082 { DecorationType::FLAT, DecorationType::NONE },
1083 { DecorationType::NO_PERSPECTIVE, DecorationType::FLAT },
1084 { DecorationType::NO_PERSPECTIVE, DecorationType::NONE },
1085 { DecorationType::COMPONENT0, DecorationType::NONE },
1086 { DecorationType::NONE, DecorationType::COMPONENT0 },
1087 };
1088
1089 de::MovePtr<tcu::TestCaseGroup> decorationMismatching(new tcu::TestCaseGroup(testCtx, "decoration_mismatch", "Decoration mismatch tests"));
1090 for (PipelineType stageType : pipelineTypeList)
1091 for (DefinitionType defType : definitionsTypeList)
1092 for (const auto& decoration : decorationPairs)
1093 {
1094 // tests component = 0 only for loose variables or member of block
1095 if (((decoration.first == DecorationType::COMPONENT0) ||
1096 (decoration.second == DecorationType::COMPONENT0)) &&
1097 ((defType != DefinitionType::LOOSE_VARIABLE) &&
1098 (defType != DefinitionType::MEMBER_OF_BLOCK)))
1099 continue;
1100
1101 auto testParams = new TestParams
1102 {
1103 TestType::DECORATION_MISMATCH,
1104 VecType::VEC4,
1105 VecType::VEC4,
1106 decoration.first,
1107 decoration.second,
1108 stageType,
1109 defType
1110 };
1111 decorationMismatching->addChild(new InterfaceMatchingTestCase(testCtx, TestParamsSp(testParams)));
1112 }
1113
1114 testGroup->addChild(decorationMismatching.release());
1115 return testGroup.release();
1116 }
1117
1118 } // pipeline
1119 } // vkt
1120