1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2014 The Android Open Source Project
6 * Copyright (c) 2016 The Khronos Group Inc.
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 Tessellation Shader Input/Output Tests
23 *//*--------------------------------------------------------------------*/
24
25 #include "vktTessellationShaderInputOutputTests.hpp"
26 #include "vktTestCaseUtil.hpp"
27 #include "vktTessellationUtil.hpp"
28
29 #include "tcuTestLog.hpp"
30 #include "tcuImageIO.hpp"
31 #include "tcuTexture.hpp"
32 #include "tcuImageCompare.hpp"
33
34 #include "vkDefs.hpp"
35 #include "vkBarrierUtil.hpp"
36 #include "vkQueryUtil.hpp"
37 #include "vkBuilderUtil.hpp"
38 #include "vkImageUtil.hpp"
39 #include "vkTypeUtil.hpp"
40 #include "vkStrUtil.hpp"
41 #include "vkCmdUtil.hpp"
42 #include "vkObjUtil.hpp"
43 #include "vkBufferWithMemory.hpp"
44 #include "vkImageWithMemory.hpp"
45
46 #include "deUniquePtr.hpp"
47 #include "deStringUtil.hpp"
48
49 #include <string>
50 #include <vector>
51
52 namespace vkt
53 {
54 namespace tessellation
55 {
56
57 using namespace vk;
58
59 namespace
60 {
61
62 enum Constants
63 {
64 RENDER_SIZE = 256,
65 };
66
67 //! Generic test code used by all test cases.
runTest(Context & context,const int numPrimitives,const int inPatchSize,const int outPatchSize,const VkFormat vertexFormat,const void * vertexData,const VkDeviceSize vertexDataSizeBytes,const tcu::ConstPixelBufferAccess & referenceImageAccess)68 tcu::TestStatus runTest (Context& context,
69 const int numPrimitives,
70 const int inPatchSize,
71 const int outPatchSize,
72 const VkFormat vertexFormat,
73 const void* vertexData,
74 const VkDeviceSize vertexDataSizeBytes,
75 const tcu::ConstPixelBufferAccess& referenceImageAccess)
76 {
77 requireFeatures(context.getInstanceInterface(), context.getPhysicalDevice(), FEATURE_TESSELLATION_SHADER);
78
79 const DeviceInterface& vk = context.getDeviceInterface();
80 const VkDevice device = context.getDevice();
81 const VkQueue queue = context.getUniversalQueue();
82 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
83 Allocator& allocator = context.getDefaultAllocator();
84
85 // Vertex input: may be just some abstract numbers
86
87 const BufferWithMemory vertexBuffer(vk, device, allocator,
88 makeBufferCreateInfo(vertexDataSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), MemoryRequirement::HostVisible);
89
90 {
91 const Allocation& alloc = vertexBuffer.getAllocation();
92
93 deMemcpy(alloc.getHostPtr(), vertexData, static_cast<std::size_t>(vertexDataSizeBytes));
94 flushAlloc(vk, device, alloc);
95 // No barrier needed, flushed memory is automatically visible
96 }
97
98 // Color attachment
99
100 const tcu::IVec2 renderSize = tcu::IVec2(RENDER_SIZE, RENDER_SIZE);
101 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
102 const VkImageSubresourceRange colorImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
103 const ImageWithMemory colorAttachmentImage (vk, device, allocator,
104 makeImageCreateInfo(renderSize, colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 1u),
105 MemoryRequirement::Any);
106
107 // Color output buffer: image will be copied here for verification
108
109 const VkDeviceSize colorBufferSizeBytes = renderSize.x()*renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat));
110 const BufferWithMemory colorBuffer (vk, device, allocator, makeBufferCreateInfo(colorBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT), MemoryRequirement::HostVisible);
111
112 // Pipeline
113
114 const Unique<VkImageView> colorAttachmentView (makeImageView (vk, device, *colorAttachmentImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorImageSubresourceRange));
115 const Unique<VkRenderPass> renderPass (makeRenderPass (vk, device, colorFormat));
116 const Unique<VkFramebuffer> framebuffer (makeFramebuffer (vk, device, *renderPass, *colorAttachmentView, renderSize.x(), renderSize.y()));
117 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout (vk, device));
118 const Unique<VkCommandPool> cmdPool (makeCommandPool (vk, device, queueFamilyIndex));
119 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
120
121 const Unique<VkPipeline> pipeline(GraphicsPipelineBuilder()
122 .setRenderSize (renderSize)
123 .setVertexInputSingleAttribute(vertexFormat, tcu::getPixelSize(mapVkFormat(vertexFormat)))
124 .setPatchControlPoints (inPatchSize)
125 .setShader (vk, device, VK_SHADER_STAGE_VERTEX_BIT, context.getBinaryCollection().get("vert"), DE_NULL)
126 .setShader (vk, device, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, context.getBinaryCollection().get("tesc"), DE_NULL)
127 .setShader (vk, device, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, context.getBinaryCollection().get("tese"), DE_NULL)
128 .setShader (vk, device, VK_SHADER_STAGE_FRAGMENT_BIT, context.getBinaryCollection().get("frag"), DE_NULL)
129 .build (vk, device, *pipelineLayout, *renderPass));
130
131 {
132 tcu::TestLog& log = context.getTestContext().getLog();
133 log << tcu::TestLog::Message
134 << "Note: input patch size is " << inPatchSize << ", output patch size is " << outPatchSize
135 << tcu::TestLog::EndMessage;
136 }
137
138 // Draw commands
139
140 beginCommandBuffer(vk, *cmdBuffer);
141
142 // Change color attachment image layout
143 {
144 const VkImageMemoryBarrier colorAttachmentLayoutBarrier = makeImageMemoryBarrier(
145 (VkAccessFlags)0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
146 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
147 *colorAttachmentImage, colorImageSubresourceRange);
148
149 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u,
150 0u, DE_NULL, 0u, DE_NULL, 1u, &colorAttachmentLayoutBarrier);
151 }
152
153 // Begin render pass
154 {
155 const VkRect2D renderArea = makeRect2D(renderSize);
156 const tcu::Vec4 clearColor (0.0f, 0.0f, 0.0f, 1.0f);
157
158 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea, clearColor);
159 }
160
161 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
162 {
163 const VkDeviceSize vertexBufferOffset = 0ull;
164 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
165 }
166
167 // Process enough vertices to make a patch.
168 vk.cmdDraw(*cmdBuffer, numPrimitives * inPatchSize, 1u, 0u, 0u);
169 endRenderPass(vk, *cmdBuffer);
170
171 // Copy render result to a host-visible buffer
172 copyImageToBuffer(vk, *cmdBuffer, *colorAttachmentImage, *colorBuffer, renderSize);
173
174 endCommandBuffer(vk, *cmdBuffer);
175 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
176
177 {
178 const Allocation& colorBufferAlloc = colorBuffer.getAllocation();
179
180 invalidateAlloc(vk, device, colorBufferAlloc);
181
182 // Verify case result
183 const tcu::ConstPixelBufferAccess resultImageAccess (mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1, colorBufferAlloc.getHostPtr());
184 tcu::TestLog& log = context.getTestContext().getLog();
185 const bool ok = tcu::fuzzyCompare(log, "ImageComparison", "Image Comparison", referenceImageAccess, resultImageAccess,
186 0.002f, tcu::COMPARE_LOG_RESULT);
187
188 return (ok ? tcu::TestStatus::pass("OK") : tcu::TestStatus::fail("Failure"));
189 }
190 }
191
192 //! Resize an image and fill with white color.
initializeWhiteReferenceImage(tcu::TextureLevel & image,const int width,const int height)193 void initializeWhiteReferenceImage (tcu::TextureLevel& image, const int width, const int height)
194 {
195 DE_ASSERT(width > 0 && height > 0);
196
197 image.setStorage(mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM), width, height);
198 tcu::PixelBufferAccess access = image.getAccess();
199
200 const tcu::Vec4 white(1.0f, 1.0f, 1.0f, 1.0f);
201
202 for (int y = 0; y < height; ++y)
203 for (int x = 0; x < width; ++x)
204 access.setPixel(white, x, y);
205 }
206
207 namespace PatchVertexCount
208 {
209
210 struct CaseDefinition
211 {
212 int inPatchSize;
213 int outPatchSize;
214 std::string referenceImagePath;
215 };
216
initPrograms(vk::SourceCollections & programCollection,const CaseDefinition caseDef)217 void initPrograms (vk::SourceCollections& programCollection, const CaseDefinition caseDef)
218 {
219 // Vertex shader
220 {
221 std::ostringstream src;
222 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
223 << "\n"
224 << "layout(location = 0) in highp float in_v_attr;\n"
225 << "layout(location = 0) out highp float in_tc_attr;\n"
226 << "\n"
227 << "void main (void)\n"
228 << "{\n"
229 << " in_tc_attr = in_v_attr;\n"
230 << "}\n";
231
232 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
233 }
234
235 // Tessellation control shader
236 {
237 std::ostringstream src;
238 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
239 << "#extension GL_EXT_tessellation_shader : require\n"
240 << "\n"
241 << "layout(vertices = " << caseDef.outPatchSize << ") out;\n"
242 << "\n"
243 << "layout(location = 0) in highp float in_tc_attr[];\n"
244 << "layout(location = 0) out highp float in_te_attr[];\n"
245 << "\n"
246 << "void main (void)\n"
247 << "{\n"
248 << " in_te_attr[gl_InvocationID] = in_tc_attr[gl_InvocationID*" << caseDef.inPatchSize << "/" << caseDef.outPatchSize << "];\n"
249 << "\n"
250 << " gl_TessLevelInner[0] = 5.0;\n"
251 << " gl_TessLevelInner[1] = 5.0;\n"
252 << "\n"
253 << " gl_TessLevelOuter[0] = 5.0;\n"
254 << " gl_TessLevelOuter[1] = 5.0;\n"
255 << " gl_TessLevelOuter[2] = 5.0;\n"
256 << " gl_TessLevelOuter[3] = 5.0;\n"
257 << "}\n";
258
259 programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str());
260 }
261
262 // Tessellation evaluation shader
263 {
264 std::ostringstream src;
265 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
266 << "#extension GL_EXT_tessellation_shader : require\n"
267 << "\n"
268 << "layout(" << getTessPrimitiveTypeShaderName(TESSPRIMITIVETYPE_QUADS) << ") in;\n"
269 << "\n"
270 << "layout(location = 0) in highp float in_te_attr[];\n"
271 << "layout(location = 0) out mediump vec4 in_f_color;\n"
272 << "\n"
273 << "void main (void)\n"
274 << "{\n"
275 << " highp float x = gl_TessCoord.x*2.0 - 1.0;\n"
276 << " highp float y = gl_TessCoord.y - in_te_attr[int(round(gl_TessCoord.x*float(" << caseDef.outPatchSize << "-1)))];\n"
277 << " gl_Position = vec4(x, y, 0.0, 1.0);\n"
278 << " in_f_color = vec4(1.0);\n"
279 << "}\n";
280
281 programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str());
282 }
283
284 // Fragment shader
285 {
286 std::ostringstream src;
287 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
288 << "\n"
289 << "layout(location = 0) in mediump vec4 in_f_color;\n"
290 << "layout(location = 0) out mediump vec4 o_color;\n"
291 << "\n"
292 << "void main (void)\n"
293 << "{\n"
294 << " o_color = in_f_color;\n"
295 << "}\n";
296
297 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
298 }
299 }
300
test(Context & context,const CaseDefinition caseDef)301 tcu::TestStatus test (Context& context, const CaseDefinition caseDef)
302 {
303 // Input vertex attribute data
304 std::vector<float> vertexData;
305 vertexData.reserve(caseDef.inPatchSize);
306 for (int i = 0; i < caseDef.inPatchSize; ++i)
307 {
308 const float f = static_cast<float>(i) / static_cast<float>(caseDef.inPatchSize - 1);
309 vertexData.push_back(f*f);
310 }
311 const VkDeviceSize vertexBufferSize = sizeof(float) * vertexData.size();
312
313 // Load reference image
314 tcu::TextureLevel referenceImage;
315 tcu::ImageIO::loadPNG(referenceImage, context.getTestContext().getArchive(), caseDef.referenceImagePath.c_str());
316
317 const int numPrimitives = 1;
318
319 return runTest(context, numPrimitives, caseDef.inPatchSize, caseDef.outPatchSize,
320 VK_FORMAT_R32_SFLOAT, &vertexData[0], vertexBufferSize, referenceImage.getAccess());
321 }
322
323 } // PatchVertexCountTest ns
324
325 namespace PerPatchData
326 {
327
328 enum CaseType
329 {
330 CASETYPE_PRIMITIVE_ID_TCS,
331 CASETYPE_PRIMITIVE_ID_TES,
332 CASETYPE_PATCH_VERTICES_IN_TCS,
333 CASETYPE_PATCH_VERTICES_IN_TES,
334 CASETYPE_TESS_LEVEL_INNER0_TES,
335 CASETYPE_TESS_LEVEL_INNER1_TES,
336 CASETYPE_TESS_LEVEL_OUTER0_TES,
337 CASETYPE_TESS_LEVEL_OUTER1_TES,
338 CASETYPE_TESS_LEVEL_OUTER2_TES,
339 CASETYPE_TESS_LEVEL_OUTER3_TES,
340 };
341
342 enum Constants
343 {
344 OUTPUT_PATCH_SIZE = 5,
345 INPUT_PATCH_SIZE = 10,
346 };
347
348 struct CaseDefinition
349 {
350 CaseType caseType;
351 std::string caseName;
352 bool usesReferenceImageFromFile;
353 std::string referenceImagePath;
354 };
355
getNumPrimitives(const CaseType type)356 int getNumPrimitives (const CaseType type)
357 {
358 return (type == CASETYPE_PRIMITIVE_ID_TCS || type == CASETYPE_PRIMITIVE_ID_TES ? 8 : 1);
359 }
360
initPrograms(vk::SourceCollections & programCollection,const CaseDefinition caseDef)361 void initPrograms (vk::SourceCollections& programCollection, const CaseDefinition caseDef)
362 {
363 // Vertex shader
364 {
365 std::ostringstream src;
366 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
367 << "\n"
368 << "layout(location = 0) in highp float in_v_attr;\n"
369 << "layout(location = 0) out highp float in_tc_attr;\n"
370 << "\n"
371 << "void main (void)\n"
372 << "{\n"
373 << " in_tc_attr = in_v_attr;\n"
374 << "}\n";
375
376 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
377 }
378
379 // Tessellation control shader
380 {
381 std::ostringstream src;
382 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
383 << "#extension GL_EXT_tessellation_shader : require\n"
384 << "\n"
385 << "layout(vertices = " << OUTPUT_PATCH_SIZE << ") out;\n"
386 << "\n"
387 << "layout(location = 0) in highp float in_tc_attr[];\n"
388 << "layout(location = 0) out highp float in_te_attr[];\n"
389 << "\n"
390 << (caseDef.caseType == CASETYPE_PRIMITIVE_ID_TCS ? "layout(location = 1) patch out mediump int in_te_primitiveIDFromTCS;\n" :
391 caseDef.caseType == CASETYPE_PATCH_VERTICES_IN_TCS ? "layout(location = 1) patch out mediump int in_te_patchVerticesInFromTCS;\n" : "")
392 << "\n"
393 << "void main (void)\n"
394 << "{\n"
395 << " in_te_attr[gl_InvocationID] = in_tc_attr[gl_InvocationID];\n"
396 << (caseDef.caseType == CASETYPE_PRIMITIVE_ID_TCS ? " in_te_primitiveIDFromTCS = gl_PrimitiveID;\n" :
397 caseDef.caseType == CASETYPE_PATCH_VERTICES_IN_TCS ? " in_te_patchVerticesInFromTCS = gl_PatchVerticesIn;\n" : "")
398 << "\n"
399 << " gl_TessLevelInner[0] = 9.0;\n"
400 << " gl_TessLevelInner[1] = 8.0;\n"
401 << "\n"
402 << " gl_TessLevelOuter[0] = 7.0;\n"
403 << " gl_TessLevelOuter[1] = 6.0;\n"
404 << " gl_TessLevelOuter[2] = 5.0;\n"
405 << " gl_TessLevelOuter[3] = 4.0;\n"
406 << "}\n";
407
408 programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str());
409 }
410
411 // Tessellation evaluation shader
412 {
413 const float xScale = 1.0f / static_cast<float>(getNumPrimitives(caseDef.caseType));
414
415 std::ostringstream src;
416 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
417 << "#extension GL_EXT_tessellation_shader : require\n"
418 << "\n"
419 << "layout(" << getTessPrimitiveTypeShaderName(TESSPRIMITIVETYPE_QUADS) << ") in;\n"
420 << "\n"
421 << "layout(location = 0) in highp float in_te_attr[];\n"
422 << "layout(location = 0) out mediump vec4 in_f_color;\n"
423 << "\n"
424 << (caseDef.caseType == CASETYPE_PRIMITIVE_ID_TCS ? "layout(location = 1) patch in mediump int in_te_primitiveIDFromTCS;\n" :
425 caseDef.caseType == CASETYPE_PATCH_VERTICES_IN_TCS ? "layout(location = 1) patch in mediump int in_te_patchVerticesInFromTCS;\n" : "")
426 << "\n"
427 << "void main (void)\n"
428 << "{\n"
429 << " highp float x = (gl_TessCoord.x*float(" << xScale << ") + in_te_attr[0]) * 2.0 - 1.0;\n"
430 << " highp float y = gl_TessCoord.y*2.0 - 1.0;\n"
431 << " gl_Position = vec4(x, y, 0.0, 1.0);\n"
432 << (caseDef.caseType == CASETYPE_PRIMITIVE_ID_TCS ? " bool ok = in_te_primitiveIDFromTCS == 3;\n" :
433 caseDef.caseType == CASETYPE_PRIMITIVE_ID_TES ? " bool ok = gl_PrimitiveID == 3;\n" :
434 caseDef.caseType == CASETYPE_PATCH_VERTICES_IN_TCS ? " bool ok = in_te_patchVerticesInFromTCS == " + de::toString(INPUT_PATCH_SIZE) + ";\n" :
435 caseDef.caseType == CASETYPE_PATCH_VERTICES_IN_TES ? " bool ok = gl_PatchVerticesIn == " + de::toString(OUTPUT_PATCH_SIZE) + ";\n" :
436 caseDef.caseType == CASETYPE_TESS_LEVEL_INNER0_TES ? " bool ok = abs(gl_TessLevelInner[0] - 9.0) < 0.1f;\n" :
437 caseDef.caseType == CASETYPE_TESS_LEVEL_INNER1_TES ? " bool ok = abs(gl_TessLevelInner[1] - 8.0) < 0.1f;\n" :
438 caseDef.caseType == CASETYPE_TESS_LEVEL_OUTER0_TES ? " bool ok = abs(gl_TessLevelOuter[0] - 7.0) < 0.1f;\n" :
439 caseDef.caseType == CASETYPE_TESS_LEVEL_OUTER1_TES ? " bool ok = abs(gl_TessLevelOuter[1] - 6.0) < 0.1f;\n" :
440 caseDef.caseType == CASETYPE_TESS_LEVEL_OUTER2_TES ? " bool ok = abs(gl_TessLevelOuter[2] - 5.0) < 0.1f;\n" :
441 caseDef.caseType == CASETYPE_TESS_LEVEL_OUTER3_TES ? " bool ok = abs(gl_TessLevelOuter[3] - 4.0) < 0.1f;\n" : "")
442 << " in_f_color = ok ? vec4(1.0) : vec4(vec3(0.0), 1.0);\n"
443 << "}\n";
444
445 programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str());
446 }
447
448 // Fragment shader
449 {
450 std::ostringstream src;
451 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
452 << "\n"
453 << "layout(location = 0) in mediump vec4 in_f_color;\n"
454 << "layout(location = 0) out mediump vec4 o_color;\n"
455 << "\n"
456 << "void main (void)\n"
457 << "{\n"
458 << " o_color = in_f_color;\n"
459 << "}\n";
460
461 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
462 }
463 }
464
test(Context & context,const CaseDefinition caseDef)465 tcu::TestStatus test (Context& context, const CaseDefinition caseDef)
466 {
467 DE_ASSERT(!caseDef.usesReferenceImageFromFile || !caseDef.referenceImagePath.empty());
468
469 // Input vertex attribute data
470 const int numPrimitives = getNumPrimitives(caseDef.caseType);
471 std::vector<float> vertexData (INPUT_PATCH_SIZE * numPrimitives, 0.0f);
472 const VkDeviceSize vertexBufferSize = sizeof(float) * vertexData.size();
473
474 for (int i = 0; i < numPrimitives; ++i)
475 vertexData[INPUT_PATCH_SIZE * i] = static_cast<float>(i) / static_cast<float>(numPrimitives);
476
477 tcu::TextureLevel referenceImage;
478 if (caseDef.usesReferenceImageFromFile)
479 tcu::ImageIO::loadPNG(referenceImage, context.getTestContext().getArchive(), caseDef.referenceImagePath.c_str());
480 else
481 initializeWhiteReferenceImage(referenceImage, RENDER_SIZE, RENDER_SIZE);
482
483 return runTest(context, numPrimitives, INPUT_PATCH_SIZE, OUTPUT_PATCH_SIZE,
484 VK_FORMAT_R32_SFLOAT, &vertexData[0], vertexBufferSize, referenceImage.getAccess());
485 }
486
487 } // PerPatchData ns
488
489 namespace GLPosition
490 {
491
492 enum CaseType
493 {
494 CASETYPE_VS_TO_TCS = 0,
495 CASETYPE_TCS_TO_TES,
496 CASETYPE_VS_TO_TCS_TO_TES,
497 };
498
initPrograms(vk::SourceCollections & programCollection,const CaseType caseType)499 void initPrograms (vk::SourceCollections& programCollection, const CaseType caseType)
500 {
501 const bool vsToTCS = caseType == CASETYPE_VS_TO_TCS || caseType == CASETYPE_VS_TO_TCS_TO_TES;
502 const bool tcsToTES = caseType == CASETYPE_TCS_TO_TES || caseType == CASETYPE_VS_TO_TCS_TO_TES;
503
504 // Vertex shader
505 {
506 std::ostringstream src;
507 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
508 << "\n"
509 << "layout(location = 0) in highp vec4 in_v_attr;\n"
510 << (!vsToTCS ? "layout(location = 0) out highp vec4 in_tc_attr;\n" : "")
511 << "\n"
512 << "void main (void)\n"
513 << "{\n"
514 << " " << (vsToTCS ? "gl_Position" : "in_tc_attr") << " = in_v_attr;\n"
515 << "}\n";
516
517 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
518 }
519
520 // Tessellation control shader
521 {
522 std::ostringstream src;
523 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
524 << "#extension GL_EXT_tessellation_shader : require\n"
525 << "\n"
526 << "layout(vertices = 3) out;\n"
527 << "\n"
528 << (!vsToTCS ? "layout(location = 0) in highp vec4 in_tc_attr[];\n" : "")
529 << (!tcsToTES ? "layout(location = 0) out highp vec4 in_te_attr[];\n" : "")
530 << "\n"
531 << "void main (void)\n"
532 << "{\n"
533 << " " << (tcsToTES ? "gl_out[gl_InvocationID].gl_Position" : "in_te_attr[gl_InvocationID]") << " = "
534 << (vsToTCS ? "gl_in[gl_InvocationID].gl_Position" : "in_tc_attr[gl_InvocationID]") << ";\n"
535 << "\n"
536 << " gl_TessLevelInner[0] = 2.0;\n"
537 << " gl_TessLevelInner[1] = 3.0;\n"
538 << "\n"
539 << " gl_TessLevelOuter[0] = 4.0;\n"
540 << " gl_TessLevelOuter[1] = 5.0;\n"
541 << " gl_TessLevelOuter[2] = 6.0;\n"
542 << " gl_TessLevelOuter[3] = 7.0;\n"
543 << "}\n";
544
545 programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str());
546 }
547
548 // Tessellation evaluation shader
549 {
550 const std::string tesIn0 = tcsToTES ? "gl_in[0].gl_Position" : "in_te_attr[0]";
551 const std::string tesIn1 = tcsToTES ? "gl_in[1].gl_Position" : "in_te_attr[1]";
552 const std::string tesIn2 = tcsToTES ? "gl_in[2].gl_Position" : "in_te_attr[2]";
553
554 std::ostringstream src;
555 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
556 << "#extension GL_EXT_tessellation_shader : require\n"
557 << "\n"
558 << "layout(" << getTessPrimitiveTypeShaderName(TESSPRIMITIVETYPE_TRIANGLES) << ") in;\n"
559 << "\n"
560 << (!tcsToTES ? "layout(location = 0) in highp vec4 in_te_attr[];\n" : "")
561 << "layout(location = 0) out highp vec4 in_f_color;\n"
562 << "\n"
563 << "void main (void)\n"
564 << "{\n"
565 << " highp vec2 xy = gl_TessCoord.x * " << tesIn0 << ".xy\n"
566 << " + gl_TessCoord.y * " << tesIn1 << ".xy\n"
567 << " + gl_TessCoord.z * " << tesIn2 << ".xy;\n"
568 << " gl_Position = vec4(xy, 0.0, 1.0);\n"
569 << " in_f_color = vec4(" << tesIn0 << ".z + " << tesIn1 << ".w,\n"
570 << " " << tesIn2 << ".z + " << tesIn0 << ".w,\n"
571 << " " << tesIn1 << ".z + " << tesIn2 << ".w,\n"
572 << " 1.0);\n"
573 << "}\n";
574
575 programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str());
576 }
577
578 // Fragment shader
579 {
580 std::ostringstream src;
581 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
582 << "\n"
583 << "layout(location = 0) in highp vec4 in_f_color;\n"
584 << "layout(location = 0) out mediump vec4 o_color;\n"
585 << "\n"
586 << "void main (void)\n"
587 << "{\n"
588 << " o_color = in_f_color;\n"
589 << "}\n";
590
591 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
592 }
593 }
594
test(Context & context,const CaseType caseType)595 tcu::TestStatus test (Context& context, const CaseType caseType)
596 {
597 DE_UNREF(caseType);
598
599 // Input vertex attribute data
600 static const float vertexData[3*4] =
601 {
602 -0.8f, -0.7f, 0.1f, 0.7f,
603 -0.5f, 0.4f, 0.2f, 0.5f,
604 0.3f, 0.2f, 0.3f, 0.45f
605 };
606
607 tcu::TextureLevel referenceImage;
608 tcu::ImageIO::loadPNG(referenceImage, context.getTestContext().getArchive(), "vulkan/data/tessellation/gl_position_ref.png");
609
610 const int numPrimitives = 1;
611 const int inPatchSize = 3;
612 const int outPatchSize = 3;
613
614 return runTest(context, numPrimitives, inPatchSize, outPatchSize,
615 VK_FORMAT_R32G32B32A32_SFLOAT, vertexData, sizeof(vertexData), referenceImage.getAccess());
616 }
617
618 } // GLPosition ns
619
620 namespace Barrier
621 {
622
623 enum Constants
624 {
625 NUM_VERTICES = 32,
626 };
627
initPrograms(vk::SourceCollections & programCollection)628 void initPrograms (vk::SourceCollections& programCollection)
629 {
630 // Vertex shader
631 {
632 std::ostringstream src;
633 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
634 << "\n"
635 << "layout(location = 0) in highp float in_v_attr;\n"
636 << "layout(location = 0) out highp float in_tc_attr;\n"
637 << "\n"
638 << "void main (void)\n"
639 << "{\n"
640 << " in_tc_attr = in_v_attr;\n"
641 << "}\n";
642
643 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
644 }
645
646 // Tessellation control shader
647 {
648 std::ostringstream src;
649 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
650 << "#extension GL_EXT_tessellation_shader : require\n"
651 << "\n"
652 << "layout(vertices = " << NUM_VERTICES << ") out;\n"
653 << "\n"
654 << "layout(location = 0) in highp float in_tc_attr[];\n"
655 << "layout(location = 0) out highp float in_te_attr[];\n"
656 << "\n"
657 << "layout(location = 1) patch out highp float in_te_patchAttr;\n"
658 << "\n"
659 << "void main (void)\n"
660 << "{\n"
661 << " in_te_attr[gl_InvocationID] = in_tc_attr[gl_InvocationID];\n"
662 << " in_te_patchAttr = 0.0f;\n"
663 << "\n"
664 << " barrier();\n"
665 << "\n"
666 << " if (gl_InvocationID == 5)\n"
667 << " in_te_patchAttr = float(gl_InvocationID)*0.1;\n"
668 << "\n"
669 << " barrier();\n"
670 << "\n"
671 << " highp float temp = in_te_patchAttr + in_te_attr[gl_InvocationID];\n"
672 << "\n"
673 << " barrier();\n"
674 << "\n"
675 << " if (gl_InvocationID == " << NUM_VERTICES << "-1)\n"
676 << " in_te_patchAttr = float(gl_InvocationID);\n"
677 << "\n"
678 << " barrier();\n"
679 << "\n"
680 << " in_te_attr[gl_InvocationID] = temp;\n"
681 << "\n"
682 << " barrier();\n"
683 << "\n"
684 << " temp = temp + in_te_attr[(gl_InvocationID+1) % " << NUM_VERTICES << "];\n"
685 << "\n"
686 << " barrier();\n"
687 << "\n"
688 << " in_te_attr[gl_InvocationID] = 0.25*temp;\n"
689 << "\n"
690 << " gl_TessLevelInner[0] = 32.0;\n"
691 << " gl_TessLevelInner[1] = 32.0;\n"
692 << "\n"
693 << " gl_TessLevelOuter[0] = 32.0;\n"
694 << " gl_TessLevelOuter[1] = 32.0;\n"
695 << " gl_TessLevelOuter[2] = 32.0;\n"
696 << " gl_TessLevelOuter[3] = 32.0;\n"
697 << "}\n";
698
699 programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str());
700 }
701
702 // Tessellation evaluation shader
703 {
704 std::ostringstream src;
705 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
706 << "#extension GL_EXT_tessellation_shader : require\n"
707 << "\n"
708 << "layout(" << getTessPrimitiveTypeShaderName(TESSPRIMITIVETYPE_QUADS) << ") in;\n"
709 << "\n"
710 << "layout(location = 0) in highp float in_te_attr[];\n"
711 << "layout(location = 1) patch in highp float in_te_patchAttr;\n"
712 << "\n"
713 << "layout(location = 0) out highp float in_f_blue;\n"
714 << "\n"
715 << "void main (void)\n"
716 << "{\n"
717 << " highp float x = gl_TessCoord.x*2.0 - 1.0;\n"
718 << " highp float y = gl_TessCoord.y - in_te_attr[int(round(gl_TessCoord.x*float(" << NUM_VERTICES << "-1)))];\n"
719 << " gl_Position = vec4(x, y, 0.0, 1.0);\n"
720 << " in_f_blue = abs(in_te_patchAttr - float(" << NUM_VERTICES << "-1));\n"
721 << "}\n";
722
723 programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str());
724 }
725
726 // Fragment shader
727 {
728 std::ostringstream src;
729 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
730 << "\n"
731 << "layout(location = 0) in highp float in_f_blue;\n"
732 << "layout(location = 0) out mediump vec4 o_color;\n"
733 << "\n"
734 << "void main (void)\n"
735 << "{\n"
736 << " o_color = vec4(1.0, 0.0, in_f_blue, 1.0);\n"
737 << "}\n";
738
739 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
740 }
741 }
742
test(Context & context)743 tcu::TestStatus test (Context& context)
744 {
745 // Input vertex attribute data
746 std::vector<float> vertexData (NUM_VERTICES);
747 const VkDeviceSize vertexBufferSize = sizeof(float) * vertexData.size();
748
749 for (int i = 0; i < NUM_VERTICES; ++i)
750 vertexData[i] = static_cast<float>(i) / (NUM_VERTICES - 1);
751
752 tcu::TextureLevel referenceImage;
753 tcu::ImageIO::loadPNG(referenceImage, context.getTestContext().getArchive(), "vulkan/data/tessellation/barrier_ref.png");
754
755 const int numPrimitives = 1;
756 const int inPatchSize = NUM_VERTICES;
757 const int outPatchSize = NUM_VERTICES;
758
759 return runTest(context, numPrimitives, inPatchSize, outPatchSize,
760 VK_FORMAT_R32_SFLOAT, &vertexData[0], vertexBufferSize, referenceImage.getAccess());
761 }
762
763 } // Barrier ns
764
765 namespace CrossInvocation
766 {
767
768 enum Constants
769 {
770 OUTPUT_PATCH_SIZE = 3,
771 INPUT_PATCH_SIZE = 10
772 };
773
774 enum CaseType
775 {
776 CASETYPE_PER_VERTEX,
777 CASETYPE_PER_PATCH
778 };
779
780 enum DataType
781 {
782 DATATYPE_INT,
783 DATATYPE_UINT,
784 DATATYPE_FLOAT,
785 DATATYPE_VEC3,
786 DATATYPE_VEC4,
787 DATATYPE_MAT4X3
788 };
789
790 struct CaseDefinition
791 {
792 CaseType caseType;
793 DataType dataType;
794 };
795
initPrograms(vk::SourceCollections & programCollection,const CaseDefinition caseDef)796 void initPrograms (vk::SourceCollections& programCollection, const CaseDefinition caseDef)
797 {
798 static const std::string typeStr[] =
799 {
800 "int",
801 "uint",
802 "float",
803 "vec3",
804 "vec4",
805 "mat4x3"
806 };
807 const std::string dataType = typeStr[caseDef.dataType];
808 const int varyingSize[] = { 1, 1, 1, 1, 1, 4 };
809
810 // Vertex shader
811 {
812 std::ostringstream src;
813 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
814 << "\n"
815 << "layout(location = 0) in highp float in_v_attr;\n"
816 << "layout(location = 0) out highp float in_tc_attr;\n"
817 << "\n"
818 << "void main (void)\n"
819 << "{\n"
820 << " in_tc_attr = in_v_attr;\n"
821 << "}\n";
822
823 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
824 }
825
826 // Tessellation control shader
827 {
828 std::ostringstream src;
829 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
830 << "#extension GL_EXT_tessellation_shader : require\n"
831 << "\n"
832 << "layout(vertices = " << OUTPUT_PATCH_SIZE << ") out;\n"
833 << "\n"
834 << "layout(location = 0) in highp float in_tc_attr[];\n"
835 << "layout(location = 0) out highp float in_te_attr[];\n"
836 << "\n";
837
838 if (caseDef.caseType == CASETYPE_PER_VERTEX)
839 src << "layout(location = 1) out mediump " << dataType << " in_te_data0[];\n"
840 << "layout(location = " << varyingSize[caseDef.dataType] + 1 << ") out mediump " << dataType << " in_te_data1[];\n";
841 else
842 src << "layout(location = 1) patch out mediump " << dataType << " in_te_data0[" << OUTPUT_PATCH_SIZE << "];\n"
843 << "layout(location = " << OUTPUT_PATCH_SIZE * varyingSize[caseDef.dataType] + 1 << ") patch out mediump " << dataType << " in_te_data1[" << OUTPUT_PATCH_SIZE << "];\n";
844
845 src << "\n"
846 << "void main (void)\n"
847 << "{\n"
848 << " " << dataType << " d = " << dataType << "(gl_InvocationID);\n"
849 << " in_te_data0[gl_InvocationID] = d;\n"
850 << " barrier();\n"
851 << " in_te_data1[gl_InvocationID] = d + in_te_data0[(gl_InvocationID + 1) % " << OUTPUT_PATCH_SIZE << "];\n"
852 << "\n"
853 << " in_te_attr[gl_InvocationID] = in_tc_attr[gl_InvocationID];\n"
854 << "\n"
855 << " gl_TessLevelInner[0] = 1.0;\n"
856 << " gl_TessLevelInner[1] = 1.0;\n"
857 << "\n"
858 << " gl_TessLevelOuter[0] = 1.0;\n"
859 << " gl_TessLevelOuter[1] = 1.0;\n"
860 << " gl_TessLevelOuter[2] = 1.0;\n"
861 << " gl_TessLevelOuter[3] = 1.0;\n"
862 << "}\n";
863
864 programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str());
865 }
866
867 // Tessellation evaluation shader
868 {
869 const float xScale = 1.0f / 8.0f;
870
871 std::ostringstream src;
872 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
873 << "#extension GL_EXT_tessellation_shader : require\n"
874 << "\n"
875 << "layout(" << getTessPrimitiveTypeShaderName(TESSPRIMITIVETYPE_QUADS) << ") in;\n"
876 << "\n"
877 << "layout(location = 0) in highp float in_te_attr[];\n"
878 << "layout(location = 0) out mediump vec4 in_f_color;\n"
879 << "\n";
880
881 if (caseDef.caseType == CASETYPE_PER_VERTEX)
882 src << "layout(location = 1) in mediump " << dataType << " in_te_data0[];\n"
883 << "layout(location = " << varyingSize[caseDef.dataType] + 1 << ") in mediump " << dataType << " in_te_data1[];\n";
884 else
885 src << "layout(location = 1) patch in mediump " << dataType << " in_te_data0[" << OUTPUT_PATCH_SIZE << "];\n"
886 << "layout(location = " << OUTPUT_PATCH_SIZE * varyingSize[caseDef.dataType] + 1 << ") patch in mediump " << dataType << " in_te_data1[" << OUTPUT_PATCH_SIZE << "];\n";
887
888 src << "\n"
889 << "void main (void)\n"
890 << "{\n"
891 << " highp float x = (gl_TessCoord.x*float(" << xScale << ") + in_te_attr[0]) * 2.0 - 1.0;\n"
892 << " highp float y = gl_TessCoord.y*2.0 - 1.0;\n"
893 << " gl_Position = vec4(x, y, 0.0, 1.0);\n"
894 << " bool ok = true;\n"
895 << " for (int i = 0; i < " << OUTPUT_PATCH_SIZE << "; i++)\n"
896 << " {\n"
897 << " int ref = i + (i + 1) % " << OUTPUT_PATCH_SIZE << ";\n"
898 << " if (in_te_data1[i] != " << dataType << "(ref)) ok = false;\n"
899 << " }\n"
900 << " in_f_color = ok ? vec4(1.0) : vec4(vec3(0.0), 1.0);\n"
901 << "}\n";
902
903 programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str());
904 }
905
906 // Fragment shader
907 {
908 std::ostringstream src;
909 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
910 << "\n"
911 << "layout(location = 0) in mediump vec4 in_f_color;\n"
912 << "layout(location = 0) out mediump vec4 o_color;\n"
913 << "\n"
914 << "void main (void)\n"
915 << "{\n"
916 << " o_color = in_f_color;\n"
917 << "}\n";
918
919 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
920 }
921 }
922
test(Context & context,const CaseDefinition caseDef)923 tcu::TestStatus test (Context& context, const CaseDefinition caseDef)
924 {
925 DE_UNREF(caseDef);
926 // Input vertex attribute data
927 const int numPrimitives = 8;
928 std::vector<float> vertexData (INPUT_PATCH_SIZE * numPrimitives, 0.0f);
929 const VkDeviceSize vertexBufferSize = sizeof(float) * vertexData.size();
930
931 for (int i = 0; i < numPrimitives; ++i)
932 vertexData[INPUT_PATCH_SIZE * i] = static_cast<float>(i) / static_cast<float>(numPrimitives);
933
934 tcu::TextureLevel referenceImage;
935 initializeWhiteReferenceImage(referenceImage, RENDER_SIZE, RENDER_SIZE);
936
937 return runTest(context, numPrimitives, INPUT_PATCH_SIZE, OUTPUT_PATCH_SIZE,
938 VK_FORMAT_R32_SFLOAT, &vertexData[0], vertexBufferSize, referenceImage.getAccess());
939 }
940
941 } // CrossInvocation ns
942
943 } // anonymous
944
945 //! These tests correspond to dEQP-GLES31.functional.tessellation.shader_input_output.*
createShaderInputOutputTests(tcu::TestContext & testCtx)946 tcu::TestCaseGroup* createShaderInputOutputTests (tcu::TestContext& testCtx)
947 {
948 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "shader_input_output"));
949
950 // Patch vertex counts
951 {
952 static const struct
953 {
954 int inPatchSize;
955 int outPatchSize;
956 } patchVertexCountCases[] =
957 {
958 { 5, 10 },
959 { 10, 5 }
960 };
961
962 for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(patchVertexCountCases); caseNdx++)
963 {
964 const int inSize = patchVertexCountCases[caseNdx].inPatchSize;
965 const int outSize = patchVertexCountCases[caseNdx].outPatchSize;
966
967 const std::string caseName = "patch_vertices_" + de::toString(inSize) + "_in_" + de::toString(outSize) + "_out";
968 const PatchVertexCount::CaseDefinition caseDef =
969 {
970 inSize, outSize, "vulkan/data/tessellation/" + caseName + "_ref.png"
971 };
972
973 // Test input and output patch vertex counts
974 addFunctionCaseWithPrograms(group.get(), caseName,
975 PatchVertexCount::initPrograms, PatchVertexCount::test, caseDef);
976 }
977 }
978
979 // Per patch data
980 {
981 static const PerPatchData::CaseDefinition cases[] =
982 {
983 // Read gl_PrimitiveID in TCS and pass it as patch output to TES
984 { PerPatchData::CASETYPE_PRIMITIVE_ID_TCS, "primitive_id_tcs", true, "vulkan/data/tessellation/primitive_id_tcs_ref.png"},
985 // Read gl_PrimitiveID in TES
986 { PerPatchData::CASETYPE_PRIMITIVE_ID_TES, "primitive_id_tes", true, "vulkan/data/tessellation/primitive_id_tes_ref.png"},
987 // Read gl_PatchVerticesIn in TCS and pass it as patch output to TES
988 { PerPatchData::CASETYPE_PATCH_VERTICES_IN_TCS, "patch_vertices_in_tcs", false, ""},
989 // Read gl_PatchVerticesIn in TES
990 { PerPatchData::CASETYPE_PATCH_VERTICES_IN_TES, "patch_vertices_in_tes", false, ""},
991 // Read gl_TessLevelInner[0] in TES
992 { PerPatchData::CASETYPE_TESS_LEVEL_INNER0_TES, "tess_level_inner_0_tes", false, ""},
993 // Read gl_TessLevelInner[1] in TES
994 { PerPatchData::CASETYPE_TESS_LEVEL_INNER1_TES, "tess_level_inner_1_tes", false, ""},
995 // Read gl_TessLevelOuter[0] in TES
996 { PerPatchData::CASETYPE_TESS_LEVEL_OUTER0_TES, "tess_level_outer_0_tes", false, ""},
997 // Read gl_TessLevelOuter[1] in TES
998 { PerPatchData::CASETYPE_TESS_LEVEL_OUTER1_TES, "tess_level_outer_1_tes", false, ""},
999 // Read gl_TessLevelOuter[2] in TES
1000 { PerPatchData::CASETYPE_TESS_LEVEL_OUTER2_TES, "tess_level_outer_2_tes", false, ""},
1001 // Read gl_TessLevelOuter[3] in TES
1002 { PerPatchData::CASETYPE_TESS_LEVEL_OUTER3_TES, "tess_level_outer_3_tes", false, ""},
1003 };
1004
1005 for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(cases); ++caseNdx)
1006 addFunctionCaseWithPrograms(group.get(), cases[caseNdx].caseName,
1007 PerPatchData::initPrograms, PerPatchData::test, cases[caseNdx]);
1008 }
1009
1010 // gl_Position
1011 {
1012 static const struct
1013 {
1014 GLPosition::CaseType type;
1015 std::string caseName;
1016 } cases[] =
1017 {
1018 { GLPosition::CASETYPE_VS_TO_TCS, "gl_position_vs_to_tcs" },
1019 { GLPosition::CASETYPE_TCS_TO_TES, "gl_position_tcs_to_tes" },
1020 { GLPosition::CASETYPE_VS_TO_TCS_TO_TES, "gl_position_vs_to_tcs_to_tes" },
1021 };
1022
1023 for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(cases); ++caseNdx) {
1024 // Pass gl_Position between VS and TCS, or between TCS and TES
1025 addFunctionCaseWithPrograms(group.get(), cases[caseNdx].caseName,
1026 GLPosition::initPrograms, GLPosition::test, cases[caseNdx].type);
1027 }
1028 }
1029
1030 // Barrier
1031 addFunctionCaseWithPrograms(group.get(), "barrier", Barrier::initPrograms, Barrier::test);
1032
1033 // Cross invocation communication
1034 {
1035 static const struct
1036 {
1037 CrossInvocation::CaseType caseType;
1038 std::string name;
1039 } caseTypes[] =
1040 {
1041 { CrossInvocation::CASETYPE_PER_VERTEX, "cross_invocation_per_vertex" },
1042 { CrossInvocation::CASETYPE_PER_PATCH, "cross_invocation_per_patch" }
1043 };
1044
1045 static const struct
1046 {
1047 CrossInvocation::DataType dataType;
1048 std::string name;
1049 } dataTypes[] =
1050 {
1051 { CrossInvocation::DATATYPE_INT, "int" },
1052 { CrossInvocation::DATATYPE_UINT, "uint" },
1053 { CrossInvocation::DATATYPE_FLOAT, "float" },
1054 { CrossInvocation::DATATYPE_VEC3, "vec3" },
1055 { CrossInvocation::DATATYPE_VEC4, "vec4" },
1056 { CrossInvocation::DATATYPE_MAT4X3, "mat4x3" }
1057 };
1058
1059 for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(caseTypes); ++caseNdx)
1060 for (int dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(dataTypes); ++dataTypeNdx)
1061 {
1062 std::string testName = caseTypes[caseNdx].name + "_" + dataTypes[dataTypeNdx].name;
1063 CrossInvocation::CaseDefinition caseDef = { caseTypes[caseNdx].caseType, dataTypes[dataTypeNdx].dataType };
1064
1065 // Write output varyings from multiple invocations.
1066 addFunctionCaseWithPrograms(group.get(), testName,
1067 CrossInvocation::initPrograms, CrossInvocation::test, caseDef);
1068 }
1069 }
1070
1071 return group.release();
1072 }
1073
1074 } // tessellation
1075 } // vkt
1076