Merge "Fix GLES2 format mismatch" into marshmallow-cts-dev am: 98dd6ac745
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / tessellation / vktTessellationShaderInputOutputTests.cpp
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 "vkQueryUtil.hpp"
36 #include "vkBuilderUtil.hpp"
37 #include "vkImageUtil.hpp"
38 #include "vkTypeUtil.hpp"
39 #include "vkStrUtil.hpp"
40
41 #include "deUniquePtr.hpp"
42 #include "deStringUtil.hpp"
43
44 #include <string>
45 #include <vector>
46
47 namespace vkt
48 {
49 namespace tessellation
50 {
51
52 using namespace vk;
53
54 namespace
55 {
56
57 enum Constants
58 {
59         RENDER_SIZE = 256,
60 };
61
62 //! Generic test code used by all test cases.
63 tcu::TestStatus runTest (Context&                                                       context,
64                                                  const int                                                      numPrimitives,
65                                                  const int                                                      inPatchSize,
66                                                  const int                                                      outPatchSize,
67                                                  const VkFormat                                         vertexFormat,
68                                                  const void*                                            vertexData,
69                                                  const VkDeviceSize                                     vertexDataSizeBytes,
70                                                  const tcu::ConstPixelBufferAccess&     referenceImageAccess)
71 {
72         requireFeatures(context.getInstanceInterface(), context.getPhysicalDevice(), FEATURE_TESSELLATION_SHADER);
73
74         const DeviceInterface&  vk                                      = context.getDeviceInterface();
75         const VkDevice                  device                          = context.getDevice();
76         const VkQueue                   queue                           = context.getUniversalQueue();
77         const deUint32                  queueFamilyIndex        = context.getUniversalQueueFamilyIndex();
78         Allocator&                              allocator                       = context.getDefaultAllocator();
79
80         // Vertex input: may be just some abstract numbers
81
82         const Buffer vertexBuffer(vk, device, allocator,
83                 makeBufferCreateInfo(vertexDataSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), MemoryRequirement::HostVisible);
84
85         {
86                 const Allocation& alloc = vertexBuffer.getAllocation();
87                 deMemcpy(alloc.getHostPtr(), vertexData, static_cast<std::size_t>(vertexDataSizeBytes));
88
89                 flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), vertexDataSizeBytes);
90                 // No barrier needed, flushed memory is automatically visible
91         }
92
93         // Color attachment
94
95         const tcu::IVec2                          renderSize                             = tcu::IVec2(RENDER_SIZE, RENDER_SIZE);
96         const VkFormat                            colorFormat                            = VK_FORMAT_R8G8B8A8_UNORM;
97         const VkImageSubresourceRange colorImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
98         const Image                                       colorAttachmentImage           (vk, device, allocator,
99                                                                                                                          makeImageCreateInfo(renderSize, colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 1u),
100                                                                                                                          MemoryRequirement::Any);
101
102         // Color output buffer: image will be copied here for verification
103
104         const VkDeviceSize      colorBufferSizeBytes = renderSize.x()*renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat));
105         const Buffer            colorBuffer                      (vk, device, allocator, makeBufferCreateInfo(colorBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT), MemoryRequirement::HostVisible);
106
107         // Pipeline
108
109         const Unique<VkImageView>               colorAttachmentView(makeImageView                                               (vk, device, *colorAttachmentImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorImageSubresourceRange));
110         const Unique<VkRenderPass>              renderPass                 (makeRenderPass                                              (vk, device, colorFormat));
111         const Unique<VkFramebuffer>             framebuffer                (makeFramebuffer                                             (vk, device, *renderPass, *colorAttachmentView, renderSize.x(), renderSize.y(), 1u));
112         const Unique<VkPipelineLayout>  pipelineLayout     (makePipelineLayoutWithoutDescriptors(vk, device));
113         const Unique<VkCommandPool>             cmdPool                    (makeCommandPool                                             (vk, device, queueFamilyIndex));
114         const Unique<VkCommandBuffer>   cmdBuffer                  (makeCommandBuffer                                   (vk, device, *cmdPool));
115
116         const Unique<VkPipeline> pipeline(GraphicsPipelineBuilder()
117                 .setRenderSize                            (renderSize)
118                 .setVertexInputSingleAttribute(vertexFormat, tcu::getPixelSize(mapVkFormat(vertexFormat)))
119                 .setPatchControlPoints            (inPatchSize)
120                 .setShader                                        (vk, device, VK_SHADER_STAGE_VERTEX_BIT,                                      context.getBinaryCollection().get("vert"), DE_NULL)
121                 .setShader                                        (vk, device, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,        context.getBinaryCollection().get("tesc"), DE_NULL)
122                 .setShader                                        (vk, device, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, context.getBinaryCollection().get("tese"), DE_NULL)
123                 .setShader                                        (vk, device, VK_SHADER_STAGE_FRAGMENT_BIT,                            context.getBinaryCollection().get("frag"), DE_NULL)
124                 .build                                            (vk, device, *pipelineLayout, *renderPass));
125
126         {
127                 tcu::TestLog& log = context.getTestContext().getLog();
128                 log << tcu::TestLog::Message
129                         << "Note: input patch size is " << inPatchSize << ", output patch size is " << outPatchSize
130                         << tcu::TestLog::EndMessage;
131         }
132
133         // Draw commands
134
135         beginCommandBuffer(vk, *cmdBuffer);
136
137         // Change color attachment image layout
138         {
139                 const VkImageMemoryBarrier colorAttachmentLayoutBarrier = makeImageMemoryBarrier(
140                         (VkAccessFlags)0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
141                         VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
142                         *colorAttachmentImage, colorImageSubresourceRange);
143
144                 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u,
145                         0u, DE_NULL, 0u, DE_NULL, 1u, &colorAttachmentLayoutBarrier);
146         }
147
148         // Begin render pass
149         {
150                 const VkRect2D renderArea = {
151                         makeOffset2D(0, 0),
152                         makeExtent2D(renderSize.x(), renderSize.y()),
153                 };
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         {
171                 const VkImageMemoryBarrier colorAttachmentPreCopyBarrier = makeImageMemoryBarrier(
172                         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
173                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
174                         *colorAttachmentImage, colorImageSubresourceRange);
175
176                 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
177                         0u, DE_NULL, 0u, DE_NULL, 1u, &colorAttachmentPreCopyBarrier);
178         }
179         {
180                 const VkBufferImageCopy copyRegion = makeBufferImageCopy(makeExtent3D(renderSize.x(), renderSize.y(), 0), makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u));
181                 vk.cmdCopyImageToBuffer(*cmdBuffer, *colorAttachmentImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, &copyRegion);
182         }
183         {
184                 const VkBufferMemoryBarrier postCopyBarrier = makeBufferMemoryBarrier(
185                         VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *colorBuffer, 0ull, colorBufferSizeBytes);
186
187                 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
188                         0u, DE_NULL, 1u, &postCopyBarrier, 0u, DE_NULL);
189         }
190
191         endCommandBuffer(vk, *cmdBuffer);
192         submitCommandsAndWait(vk, device, queue, *cmdBuffer);
193
194         {
195                 const Allocation& colorBufferAlloc = colorBuffer.getAllocation();
196                 invalidateMappedMemoryRange(vk, device, colorBufferAlloc.getMemory(), colorBufferAlloc.getOffset(), colorBufferSizeBytes);
197
198                 // Verify case result
199                 const tcu::ConstPixelBufferAccess resultImageAccess(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1, colorBufferAlloc.getHostPtr());
200                 tcu::TestLog& log = context.getTestContext().getLog();
201                 const bool ok = tcu::fuzzyCompare(log, "ImageComparison", "Image Comparison", referenceImageAccess, resultImageAccess, 0.002f, tcu::COMPARE_LOG_RESULT);
202
203                 return (ok ? tcu::TestStatus::pass("OK") : tcu::TestStatus::fail("Failure"));
204         }
205 }
206
207 namespace PatchVertexCount
208 {
209
210 struct CaseDefinition
211 {
212         int                             inPatchSize;
213         int                             outPatchSize;
214         std::string             referenceImagePath;
215 };
216
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
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         std::string             caseDescription;
355 };
356
357 int getNumPrimitives (const CaseType type)
358 {
359         return (type == CASETYPE_PRIMITIVE_ID_TCS || type == CASETYPE_PRIMITIVE_ID_TES ? 8 : 1);
360 }
361
362 void initPrograms (vk::SourceCollections& programCollection, const CaseDefinition caseDef)
363 {
364         // Vertex shader
365         {
366                 std::ostringstream src;
367                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
368                         << "\n"
369                         << "layout(location = 0) in  highp float in_v_attr;\n"
370                         << "layout(location = 0) out highp float in_tc_attr;\n"
371                         << "\n"
372                         << "void main (void)\n"
373                         << "{\n"
374                         << "    in_tc_attr = in_v_attr;\n"
375                         << "}\n";
376
377                 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
378         }
379
380         // Tessellation control shader
381         {
382                 std::ostringstream src;
383                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
384                         << "#extension GL_EXT_tessellation_shader : require\n"
385                         << "\n"
386                         << "layout(vertices = " << OUTPUT_PATCH_SIZE << ") out;\n"
387                         << "\n"
388                         << "layout(location = 0) in  highp float in_tc_attr[];\n"
389                         << "layout(location = 0) out highp float in_te_attr[];\n"
390                         << "\n"
391                         << (caseDef.caseType == CASETYPE_PRIMITIVE_ID_TCS          ? "layout(location = 1) patch out mediump int in_te_primitiveIDFromTCS;\n" :
392                                 caseDef.caseType == CASETYPE_PATCH_VERTICES_IN_TCS ? "layout(location = 1) patch out mediump int in_te_patchVerticesInFromTCS;\n" : "")
393                         << "\n"
394                         << "void main (void)\n"
395                         << "{\n"
396                         << "    in_te_attr[gl_InvocationID] = in_tc_attr[gl_InvocationID];\n"
397                         << (caseDef.caseType == CASETYPE_PRIMITIVE_ID_TCS          ? "    in_te_primitiveIDFromTCS = gl_PrimitiveID;\n" :
398                                 caseDef.caseType == CASETYPE_PATCH_VERTICES_IN_TCS ? "    in_te_patchVerticesInFromTCS = gl_PatchVerticesIn;\n" : "")
399                         << "\n"
400                         << "    gl_TessLevelInner[0] = 9.0;\n"
401                         << "    gl_TessLevelInner[1] = 8.0;\n"
402                         << "\n"
403                         << "    gl_TessLevelOuter[0] = 7.0;\n"
404                         << "    gl_TessLevelOuter[1] = 6.0;\n"
405                         << "    gl_TessLevelOuter[2] = 5.0;\n"
406                         << "    gl_TessLevelOuter[3] = 4.0;\n"
407                         << "}\n";
408
409                 programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str());
410         }
411
412         // Tessellation evaluation shader
413         {
414                 const float xScale = 1.0f / static_cast<float>(getNumPrimitives(caseDef.caseType));
415
416                 std::ostringstream src;
417                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
418                         << "#extension GL_EXT_tessellation_shader : require\n"
419                         << "\n"
420                         << "layout(" << getTessPrimitiveTypeShaderName(TESSPRIMITIVETYPE_QUADS) << ") in;\n"
421                         << "\n"
422                         << "layout(location = 0) in  highp   float in_te_attr[];\n"
423                         << "layout(location = 0) out mediump vec4  in_f_color;\n"
424                         << "\n"
425                         << (caseDef.caseType == CASETYPE_PRIMITIVE_ID_TCS          ? "layout(location = 1) patch in mediump int in_te_primitiveIDFromTCS;\n" :
426                                 caseDef.caseType == CASETYPE_PATCH_VERTICES_IN_TCS ? "layout(location = 1) patch in mediump int in_te_patchVerticesInFromTCS;\n" : "")
427                         << "\n"
428                         << "void main (void)\n"
429                         << "{\n"
430                         << "    highp float x = (gl_TessCoord.x*float(" << xScale << ") + in_te_attr[0]) * 2.0 - 1.0;\n"
431                         << "    highp float y = gl_TessCoord.y*2.0 - 1.0;\n"
432                         << "    gl_Position = vec4(x, y, 0.0, 1.0);\n"
433                         << (caseDef.caseType == CASETYPE_PRIMITIVE_ID_TCS               ? "    bool ok = in_te_primitiveIDFromTCS == 3;\n" :
434                                 caseDef.caseType == CASETYPE_PRIMITIVE_ID_TES           ? "    bool ok = gl_PrimitiveID == 3;\n" :
435                                 caseDef.caseType == CASETYPE_PATCH_VERTICES_IN_TCS      ? "    bool ok = in_te_patchVerticesInFromTCS == " + de::toString(INPUT_PATCH_SIZE) + ";\n" :
436                                 caseDef.caseType == CASETYPE_PATCH_VERTICES_IN_TES      ? "    bool ok = gl_PatchVerticesIn == " + de::toString(OUTPUT_PATCH_SIZE) + ";\n" :
437                                 caseDef.caseType == CASETYPE_TESS_LEVEL_INNER0_TES      ? "    bool ok = abs(gl_TessLevelInner[0] - 9.0) < 0.1f;\n" :
438                                 caseDef.caseType == CASETYPE_TESS_LEVEL_INNER1_TES      ? "    bool ok = abs(gl_TessLevelInner[1] - 8.0) < 0.1f;\n" :
439                                 caseDef.caseType == CASETYPE_TESS_LEVEL_OUTER0_TES      ? "    bool ok = abs(gl_TessLevelOuter[0] - 7.0) < 0.1f;\n" :
440                                 caseDef.caseType == CASETYPE_TESS_LEVEL_OUTER1_TES      ? "    bool ok = abs(gl_TessLevelOuter[1] - 6.0) < 0.1f;\n" :
441                                 caseDef.caseType == CASETYPE_TESS_LEVEL_OUTER2_TES      ? "    bool ok = abs(gl_TessLevelOuter[2] - 5.0) < 0.1f;\n" :
442                                 caseDef.caseType == CASETYPE_TESS_LEVEL_OUTER3_TES      ? "    bool ok = abs(gl_TessLevelOuter[3] - 4.0) < 0.1f;\n" : "")
443                         << "    in_f_color = ok ? vec4(1.0) : vec4(vec3(0.0), 1.0);\n"
444                         << "}\n";
445
446                 programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str());
447         }
448
449         // Fragment shader
450         {
451                 std::ostringstream src;
452                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
453                         << "\n"
454                         << "layout(location = 0) in  mediump vec4 in_f_color;\n"
455                         << "layout(location = 0) out mediump vec4 o_color;\n"
456                         << "\n"
457                         << "void main (void)\n"
458                         << "{\n"
459                         << "    o_color = in_f_color;\n"
460                         << "}\n";
461
462                 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
463         }
464 }
465
466 //! Resize an image and fill with white color.
467 void initializeWhiteReferenceImage (tcu::TextureLevel& image, const int width, const int height)
468 {
469         DE_ASSERT(width > 0 && height > 0);
470
471         image.setStorage(mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM), width, height);
472         tcu::PixelBufferAccess access = image.getAccess();
473
474         const tcu::Vec4 white(1.0f, 1.0f, 1.0f, 1.0f);
475
476         for (int y = 0; y < height; ++y)
477         for (int x = 0; x < width; ++x)
478                 access.setPixel(white, x, y);
479 }
480
481 tcu::TestStatus test (Context& context, const CaseDefinition caseDef)
482 {
483         DE_ASSERT(!caseDef.usesReferenceImageFromFile || !caseDef.referenceImagePath.empty());
484
485         // Input vertex attribute data
486         const int                  numPrimitives        = getNumPrimitives(caseDef.caseType);
487         std::vector<float> vertexData           (INPUT_PATCH_SIZE * numPrimitives, 0.0f);
488         const VkDeviceSize vertexBufferSize = sizeof(float) * vertexData.size();
489
490         for (int i = 0; i < numPrimitives; ++i)
491                 vertexData[INPUT_PATCH_SIZE * i] = static_cast<float>(i) / static_cast<float>(numPrimitives);
492
493         tcu::TextureLevel referenceImage;
494         if (caseDef.usesReferenceImageFromFile)
495                 tcu::ImageIO::loadPNG(referenceImage, context.getTestContext().getArchive(), caseDef.referenceImagePath.c_str());
496         else
497                 initializeWhiteReferenceImage(referenceImage, RENDER_SIZE, RENDER_SIZE);
498
499         return runTest(context, numPrimitives, INPUT_PATCH_SIZE, OUTPUT_PATCH_SIZE,
500                                    VK_FORMAT_R32_SFLOAT, &vertexData[0], vertexBufferSize, referenceImage.getAccess());
501 }
502
503 } // PerPatchData ns
504
505 namespace GLPosition
506 {
507
508 enum CaseType
509 {
510         CASETYPE_VS_TO_TCS = 0,
511         CASETYPE_TCS_TO_TES,
512         CASETYPE_VS_TO_TCS_TO_TES,
513 };
514
515 void initPrograms (vk::SourceCollections& programCollection, const CaseType caseType)
516 {
517         const bool vsToTCS  = caseType == CASETYPE_VS_TO_TCS  || caseType == CASETYPE_VS_TO_TCS_TO_TES;
518         const bool tcsToTES = caseType == CASETYPE_TCS_TO_TES || caseType == CASETYPE_VS_TO_TCS_TO_TES;
519
520         // Vertex shader
521         {
522                 std::ostringstream src;
523                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
524                         << "\n"
525                         << "layout(location = 0) in  highp vec4 in_v_attr;\n"
526                         << (!vsToTCS ? "layout(location = 0) out highp vec4 in_tc_attr;\n" : "")
527                         << "\n"
528                         << "void main (void)\n"
529                         << "{\n"
530                         << "    " << (vsToTCS ? "gl_Position" : "in_tc_attr") << " = in_v_attr;\n"
531                         << "}\n";
532
533                 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
534         }
535
536         // Tessellation control shader
537         {
538                 std::ostringstream src;
539                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
540                         << "#extension GL_EXT_tessellation_shader : require\n"
541                         << "\n"
542                         << "layout(vertices = 3) out;\n"
543                         << "\n"
544                         << (!vsToTCS  ? "layout(location = 0) in  highp vec4 in_tc_attr[];\n" : "")
545                         << (!tcsToTES ? "layout(location = 0) out highp vec4 in_te_attr[];\n" : "")
546                         << "\n"
547                         << "void main (void)\n"
548                         << "{\n"
549                         << "    " << (tcsToTES ? "gl_out[gl_InvocationID].gl_Position" : "in_te_attr[gl_InvocationID]") << " = "
550                                           << (vsToTCS  ? "gl_in[gl_InvocationID].gl_Position" : "in_tc_attr[gl_InvocationID]") << ";\n"
551                         << "\n"
552                         << "    gl_TessLevelInner[0] = 2.0;\n"
553                         << "    gl_TessLevelInner[1] = 3.0;\n"
554                         << "\n"
555                         << "    gl_TessLevelOuter[0] = 4.0;\n"
556                         << "    gl_TessLevelOuter[1] = 5.0;\n"
557                         << "    gl_TessLevelOuter[2] = 6.0;\n"
558                         << "    gl_TessLevelOuter[3] = 7.0;\n"
559                         << "}\n";
560
561                 programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str());
562         }
563
564         // Tessellation evaluation shader
565         {
566                 const std::string tesIn0 = tcsToTES ? "gl_in[0].gl_Position" : "in_te_attr[0]";
567                 const std::string tesIn1 = tcsToTES ? "gl_in[1].gl_Position" : "in_te_attr[1]";
568                 const std::string tesIn2 = tcsToTES ? "gl_in[2].gl_Position" : "in_te_attr[2]";
569
570                 std::ostringstream src;
571                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
572                         << "#extension GL_EXT_tessellation_shader : require\n"
573                         << "\n"
574                         << "layout(" << getTessPrimitiveTypeShaderName(TESSPRIMITIVETYPE_TRIANGLES) << ") in;\n"
575                         << "\n"
576                         << (!tcsToTES ? "layout(location = 0) in  highp vec4 in_te_attr[];\n" : "")
577                         << "layout(location = 0) out highp vec4 in_f_color;\n"
578                         << "\n"
579                         << "void main (void)\n"
580                         << "{\n"
581                         << "    highp vec2 xy = gl_TessCoord.x * " << tesIn0 << ".xy\n"
582                         << "                  + gl_TessCoord.y * " << tesIn1 << ".xy\n"
583                         << "                  + gl_TessCoord.z * " << tesIn2 << ".xy;\n"
584                         << "    gl_Position = vec4(xy, 0.0, 1.0);\n"
585                         << "    in_f_color = vec4(" << tesIn0 << ".z + " << tesIn1 << ".w,\n"
586                         << "                      " << tesIn2 << ".z + " << tesIn0 << ".w,\n"
587                         << "                      " << tesIn1 << ".z + " << tesIn2 << ".w,\n"
588                         << "                      1.0);\n"
589                         << "}\n";
590
591                 programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str());
592         }
593
594         // Fragment shader
595         {
596                 std::ostringstream src;
597                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
598                         << "\n"
599                         << "layout(location = 0) in  highp   vec4 in_f_color;\n"
600                         << "layout(location = 0) out mediump vec4 o_color;\n"
601                         << "\n"
602                         << "void main (void)\n"
603                         << "{\n"
604                         << "    o_color = in_f_color;\n"
605                         << "}\n";
606
607                 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
608         }
609 }
610
611 tcu::TestStatus test (Context& context, const CaseType caseType)
612 {
613         DE_UNREF(caseType);
614
615         // Input vertex attribute data
616         static const float vertexData[3*4] =
617         {
618                 -0.8f, -0.7f, 0.1f, 0.7f,
619                 -0.5f,  0.4f, 0.2f, 0.5f,
620                  0.3f,  0.2f, 0.3f, 0.45f
621         };
622
623         tcu::TextureLevel referenceImage;
624         tcu::ImageIO::loadPNG(referenceImage, context.getTestContext().getArchive(), "vulkan/data/tessellation/gl_position_ref.png");
625
626         const int numPrimitives = 1;
627         const int inPatchSize   = 3;
628         const int outPatchSize  = 3;
629
630         return runTest(context, numPrimitives, inPatchSize, outPatchSize,
631                                    VK_FORMAT_R32G32B32A32_SFLOAT, vertexData, sizeof(vertexData), referenceImage.getAccess());
632 }
633
634 } // GLPosition ns
635
636 namespace Barrier
637 {
638
639 enum Constants
640 {
641         NUM_VERTICES = 32,
642 };
643
644 void initPrograms (vk::SourceCollections& programCollection)
645 {
646         // Vertex shader
647         {
648                 std::ostringstream src;
649                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
650                         << "\n"
651                         << "layout(location = 0) in  highp float in_v_attr;\n"
652                         << "layout(location = 0) out highp float in_tc_attr;\n"
653                         << "\n"
654                         << "void main (void)\n"
655                         << "{\n"
656                         << "    in_tc_attr = in_v_attr;\n"
657                         << "}\n";
658
659                 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
660         }
661
662         // Tessellation control shader
663         {
664                 std::ostringstream src;
665                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
666                         << "#extension GL_EXT_tessellation_shader : require\n"
667                         << "\n"
668                         << "layout(vertices = " << NUM_VERTICES << ") out;\n"
669                         << "\n"
670                         << "layout(location = 0) in  highp float in_tc_attr[];\n"
671                         << "layout(location = 0) out highp float in_te_attr[];\n"
672                         << "\n"
673                         << "layout(location = 1) patch out highp float in_te_patchAttr;\n"
674                         << "\n"
675                         << "void main (void)\n"
676                         << "{\n"
677                         << "    in_te_attr[gl_InvocationID] = in_tc_attr[gl_InvocationID];\n"
678                         << "    in_te_patchAttr = 0.0f;\n"
679                         << "\n"
680                         << "    barrier();\n"
681                         << "\n"
682                         << "    if (gl_InvocationID == 5)\n"
683                         << "            in_te_patchAttr = float(gl_InvocationID)*0.1;\n"
684                         << "\n"
685                         << "    barrier();\n"
686                         << "\n"
687                         << "    highp float temp = in_te_patchAttr + in_te_attr[gl_InvocationID];\n"
688                         << "\n"
689                         << "    barrier();\n"
690                         << "\n"
691                         << "    if (gl_InvocationID == " << NUM_VERTICES << "-1)\n"
692                         << "            in_te_patchAttr = float(gl_InvocationID);\n"
693                         << "\n"
694                         << "    barrier();\n"
695                         << "\n"
696                         << "    in_te_attr[gl_InvocationID] = temp;\n"
697                         << "\n"
698                         << "    barrier();\n"
699                         << "\n"
700                         << "    temp = temp + in_te_attr[(gl_InvocationID+1) % " << NUM_VERTICES << "];\n"
701                         << "\n"
702                         << "    barrier();\n"
703                         << "\n"
704                         << "    in_te_attr[gl_InvocationID] = 0.25*temp;\n"
705                         << "\n"
706                         << "    gl_TessLevelInner[0] = 32.0;\n"
707                         << "    gl_TessLevelInner[1] = 32.0;\n"
708                         << "\n"
709                         << "    gl_TessLevelOuter[0] = 32.0;\n"
710                         << "    gl_TessLevelOuter[1] = 32.0;\n"
711                         << "    gl_TessLevelOuter[2] = 32.0;\n"
712                         << "    gl_TessLevelOuter[3] = 32.0;\n"
713                         << "}\n";
714
715                 programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str());
716         }
717
718         // Tessellation evaluation shader
719         {
720                 std::ostringstream src;
721                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
722                         << "#extension GL_EXT_tessellation_shader : require\n"
723                         << "\n"
724                         << "layout(" << getTessPrimitiveTypeShaderName(TESSPRIMITIVETYPE_QUADS) << ") in;\n"
725                         << "\n"
726                         << "layout(location = 0) in       highp float in_te_attr[];\n"
727                         << "layout(location = 1) patch in highp float in_te_patchAttr;\n"
728                         << "\n"
729                         << "layout(location = 0) out highp float in_f_blue;\n"
730                         << "\n"
731                         << "void main (void)\n"
732                         << "{\n"
733                         << "    highp float x = gl_TessCoord.x*2.0 - 1.0;\n"
734                         << "    highp float y = gl_TessCoord.y - in_te_attr[int(round(gl_TessCoord.x*float(" << NUM_VERTICES << "-1)))];\n"
735                         << "    gl_Position = vec4(x, y, 0.0, 1.0);\n"
736                         << "    in_f_blue = abs(in_te_patchAttr - float(" << NUM_VERTICES << "-1));\n"
737                         << "}\n";
738
739                 programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str());
740         }
741
742         // Fragment shader
743         {
744                 std::ostringstream src;
745                 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
746                         << "\n"
747                         << "layout(location = 0) in  highp   float in_f_blue;\n"
748                         << "layout(location = 0) out mediump vec4  o_color;\n"
749                         << "\n"
750                         << "void main (void)\n"
751                         << "{\n"
752                         << "    o_color = vec4(1.0, 0.0, in_f_blue, 1.0);\n"
753                         << "}\n";
754
755                 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
756         }
757 }
758
759 tcu::TestStatus test (Context& context)
760 {
761         // Input vertex attribute data
762         std::vector<float> vertexData           (NUM_VERTICES);
763         const VkDeviceSize vertexBufferSize = sizeof(float) * vertexData.size();
764
765         for (int i = 0; i < NUM_VERTICES; ++i)
766                 vertexData[i] = static_cast<float>(i) / (NUM_VERTICES - 1);
767
768         tcu::TextureLevel referenceImage;
769         tcu::ImageIO::loadPNG(referenceImage, context.getTestContext().getArchive(), "vulkan/data/tessellation/barrier_ref.png");
770
771         const int numPrimitives = 1;
772         const int inPatchSize   = NUM_VERTICES;
773         const int outPatchSize  = NUM_VERTICES;
774
775         return runTest(context, numPrimitives, inPatchSize, outPatchSize,
776                                    VK_FORMAT_R32_SFLOAT, &vertexData[0], vertexBufferSize, referenceImage.getAccess());
777 }
778
779 } // Barrier ns
780
781 } // anonymous
782
783 //! These tests correspond to dEQP-GLES31.functional.tessellation.shader_input_output.*
784 tcu::TestCaseGroup* createShaderInputOutputTests (tcu::TestContext& testCtx)
785 {
786         de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "shader_input_output", "Test tessellation control and evaluation shader inputs and outputs"));
787
788         // Patch vertex counts
789         {
790                 static const struct
791                 {
792                         int inPatchSize;
793                         int outPatchSize;
794                 } patchVertexCountCases[] =
795                 {
796                         {  5, 10 },
797                         { 10,  5 }
798                 };
799
800                 for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(patchVertexCountCases); caseNdx++)
801                 {
802                         const int inSize        = patchVertexCountCases[caseNdx].inPatchSize;
803                         const int outSize       = patchVertexCountCases[caseNdx].outPatchSize;
804
805                         const std::string caseName = "patch_vertices_" + de::toString(inSize) + "_in_" + de::toString(outSize) + "_out";
806                         const PatchVertexCount::CaseDefinition caseDef =
807                         {
808                                 inSize, outSize, "vulkan/data/tessellation/" + caseName + "_ref.png"
809                         };
810
811                         addFunctionCaseWithPrograms(group.get(), caseName, "Test input and output patch vertex counts",
812                                                                                 PatchVertexCount::initPrograms, PatchVertexCount::test, caseDef);
813                 }
814         }
815
816         // Per patch data
817         {
818                 static const PerPatchData::CaseDefinition cases[] =
819                 {
820                         { 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" },
821                         { PerPatchData::CASETYPE_PRIMITIVE_ID_TES,              "primitive_id_tes",               true, "vulkan/data/tessellation/primitive_id_tes_ref.png", "Read gl_PrimitiveID in TES" },
822                         { PerPatchData::CASETYPE_PATCH_VERTICES_IN_TCS, "patch_vertices_in_tcs",  false, "", "Read gl_PatchVerticesIn in TCS and pass it as patch output to TES" },
823                         { PerPatchData::CASETYPE_PATCH_VERTICES_IN_TES, "patch_vertices_in_tes",  false, "", "Read gl_PatchVerticesIn in TES" },
824                         { PerPatchData::CASETYPE_TESS_LEVEL_INNER0_TES, "tess_level_inner_0_tes", false, "", "Read gl_TessLevelInner[0] in TES" },
825                         { PerPatchData::CASETYPE_TESS_LEVEL_INNER1_TES, "tess_level_inner_1_tes", false, "", "Read gl_TessLevelInner[1] in TES" },
826                         { PerPatchData::CASETYPE_TESS_LEVEL_OUTER0_TES, "tess_level_outer_0_tes", false, "", "Read gl_TessLevelOuter[0] in TES" },
827                         { PerPatchData::CASETYPE_TESS_LEVEL_OUTER1_TES, "tess_level_outer_1_tes", false, "", "Read gl_TessLevelOuter[1] in TES" },
828                         { PerPatchData::CASETYPE_TESS_LEVEL_OUTER2_TES, "tess_level_outer_2_tes", false, "", "Read gl_TessLevelOuter[2] in TES" },
829                         { PerPatchData::CASETYPE_TESS_LEVEL_OUTER3_TES, "tess_level_outer_3_tes", false, "", "Read gl_TessLevelOuter[3] in TES" },
830                 };
831
832                 for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(cases); ++caseNdx)
833                         addFunctionCaseWithPrograms(group.get(), cases[caseNdx].caseName, cases[caseNdx].caseDescription,
834                                                                                 PerPatchData::initPrograms, PerPatchData::test, cases[caseNdx]);
835         }
836
837         // gl_Position
838         {
839                 static const struct
840                 {
841                         GLPosition::CaseType    type;
842                         std::string                             caseName;
843                 } cases[] =
844                 {
845                         { GLPosition::CASETYPE_VS_TO_TCS,                "gl_position_vs_to_tcs"                },
846                         { GLPosition::CASETYPE_TCS_TO_TES,               "gl_position_tcs_to_tes"               },
847                         { GLPosition::CASETYPE_VS_TO_TCS_TO_TES, "gl_position_vs_to_tcs_to_tes" },
848                 };
849
850                 for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(cases); ++caseNdx)
851                         addFunctionCaseWithPrograms(group.get(), cases[caseNdx].caseName, "Pass gl_Position between VS and TCS, or between TCS and TES",
852                                                                                 GLPosition::initPrograms, GLPosition::test, cases[caseNdx].type);
853         }
854
855         // Barrier
856         addFunctionCaseWithPrograms(group.get(), "barrier", "Basic barrier usage", Barrier::initPrograms, Barrier::test);
857
858         return group.release();
859 }
860
861 } // tessellation
862 } // vkt