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