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