1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2014 The Android Open Source Project
6 * Copyright (c) 2016 The Khronos Group Inc.
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 * \brief Tessellation Shader Input/Output Tests
23 *//*--------------------------------------------------------------------*/
25 #include "vktTessellationShaderInputOutputTests.hpp"
26 #include "vktTestCaseUtil.hpp"
27 #include "vktTessellationUtil.hpp"
29 #include "tcuTestLog.hpp"
30 #include "tcuImageIO.hpp"
31 #include "tcuTexture.hpp"
32 #include "tcuImageCompare.hpp"
35 #include "vkQueryUtil.hpp"
36 #include "vkBuilderUtil.hpp"
37 #include "vkImageUtil.hpp"
38 #include "vkTypeUtil.hpp"
39 #include "vkStrUtil.hpp"
41 #include "deUniquePtr.hpp"
42 #include "deStringUtil.hpp"
49 namespace tessellation
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)
72 requireFeatures(context.getInstanceInterface(), context.getPhysicalDevice(), FEATURE_TESSELLATION_SHADER);
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();
80 // Vertex input: may be just some abstract numbers
82 const Buffer vertexBuffer(vk, device, allocator,
83 makeBufferCreateInfo(vertexDataSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), MemoryRequirement::HostVisible);
86 const Allocation& alloc = vertexBuffer.getAllocation();
87 deMemcpy(alloc.getHostPtr(), vertexData, static_cast<std::size_t>(vertexDataSizeBytes));
89 flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), vertexDataSizeBytes);
90 // No barrier needed, flushed memory is automatically visible
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);
102 // Color output buffer: image will be copied here for verification
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);
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));
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));
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;
135 beginCommandBuffer(vk, *cmdBuffer);
137 // Change color attachment image layout
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);
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);
150 const VkRect2D renderArea = {
152 makeExtent2D(renderSize.x(), renderSize.y()),
154 const tcu::Vec4 clearColor(0.0f, 0.0f, 0.0f, 1.0f);
156 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea, clearColor);
159 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
161 const VkDeviceSize vertexBufferOffset = 0ull;
162 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
165 // Process enough vertices to make a patch.
166 vk.cmdDraw(*cmdBuffer, numPrimitives * inPatchSize, 1u, 0u, 0u);
167 endRenderPass(vk, *cmdBuffer);
169 // Copy render result to a host-visible buffer
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);
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);
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, ©Region);
184 const VkBufferMemoryBarrier postCopyBarrier = makeBufferMemoryBarrier(
185 VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *colorBuffer, 0ull, colorBufferSizeBytes);
187 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
188 0u, DE_NULL, 1u, &postCopyBarrier, 0u, DE_NULL);
191 endCommandBuffer(vk, *cmdBuffer);
192 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
195 const Allocation& colorBufferAlloc = colorBuffer.getAllocation();
196 invalidateMappedMemoryRange(vk, device, colorBufferAlloc.getMemory(), colorBufferAlloc.getOffset(), colorBufferSizeBytes);
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);
203 return (ok ? tcu::TestStatus::pass("OK") : tcu::TestStatus::fail("Failure"));
207 namespace PatchVertexCount
210 struct CaseDefinition
214 std::string referenceImagePath;
217 void initPrograms (vk::SourceCollections& programCollection, const CaseDefinition caseDef)
221 std::ostringstream src;
222 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
224 << "layout(location = 0) in highp float in_v_attr;\n"
225 << "layout(location = 0) out highp float in_tc_attr;\n"
227 << "void main (void)\n"
229 << " in_tc_attr = in_v_attr;\n"
232 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
235 // Tessellation control shader
237 std::ostringstream src;
238 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
239 << "#extension GL_EXT_tessellation_shader : require\n"
241 << "layout(vertices = " << caseDef.outPatchSize << ") out;\n"
243 << "layout(location = 0) in highp float in_tc_attr[];\n"
244 << "layout(location = 0) out highp float in_te_attr[];\n"
246 << "void main (void)\n"
248 << " in_te_attr[gl_InvocationID] = in_tc_attr[gl_InvocationID*" << caseDef.inPatchSize << "/" << caseDef.outPatchSize << "];\n"
250 << " gl_TessLevelInner[0] = 5.0;\n"
251 << " gl_TessLevelInner[1] = 5.0;\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"
259 programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str());
262 // Tessellation evaluation shader
264 std::ostringstream src;
265 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
266 << "#extension GL_EXT_tessellation_shader : require\n"
268 << "layout(" << getTessPrimitiveTypeShaderName(TESSPRIMITIVETYPE_QUADS) << ") in;\n"
270 << "layout(location = 0) in highp float in_te_attr[];\n"
271 << "layout(location = 0) out mediump vec4 in_f_color;\n"
273 << "void main (void)\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"
281 programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str());
286 std::ostringstream src;
287 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
289 << "layout(location = 0) in mediump vec4 in_f_color;\n"
290 << "layout(location = 0) out mediump vec4 o_color;\n"
292 << "void main (void)\n"
294 << " o_color = in_f_color;\n"
297 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
301 tcu::TestStatus test (Context& context, const CaseDefinition caseDef)
303 // Input vertex attribute data
304 std::vector<float> vertexData;
305 vertexData.reserve(caseDef.inPatchSize);
306 for (int i = 0; i < caseDef.inPatchSize; ++i)
308 const float f = static_cast<float>(i) / static_cast<float>(caseDef.inPatchSize - 1);
309 vertexData.push_back(f*f);
311 const VkDeviceSize vertexBufferSize = sizeof(float) * vertexData.size();
313 // Load reference image
314 tcu::TextureLevel referenceImage;
315 tcu::ImageIO::loadPNG(referenceImage, context.getTestContext().getArchive(), caseDef.referenceImagePath.c_str());
317 const int numPrimitives = 1;
319 return runTest(context, numPrimitives, caseDef.inPatchSize, caseDef.outPatchSize,
320 VK_FORMAT_R32_SFLOAT, &vertexData[0], vertexBufferSize, referenceImage.getAccess());
323 } // PatchVertexCountTest ns
325 namespace PerPatchData
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,
344 OUTPUT_PATCH_SIZE = 5,
345 INPUT_PATCH_SIZE = 10,
348 struct CaseDefinition
351 std::string caseName;
352 bool usesReferenceImageFromFile;
353 std::string referenceImagePath;
354 std::string caseDescription;
357 int getNumPrimitives (const CaseType type)
359 return (type == CASETYPE_PRIMITIVE_ID_TCS || type == CASETYPE_PRIMITIVE_ID_TES ? 8 : 1);
362 void initPrograms (vk::SourceCollections& programCollection, const CaseDefinition caseDef)
366 std::ostringstream src;
367 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
369 << "layout(location = 0) in highp float in_v_attr;\n"
370 << "layout(location = 0) out highp float in_tc_attr;\n"
372 << "void main (void)\n"
374 << " in_tc_attr = in_v_attr;\n"
377 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
380 // Tessellation control shader
382 std::ostringstream src;
383 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
384 << "#extension GL_EXT_tessellation_shader : require\n"
386 << "layout(vertices = " << OUTPUT_PATCH_SIZE << ") out;\n"
388 << "layout(location = 0) in highp float in_tc_attr[];\n"
389 << "layout(location = 0) out highp float in_te_attr[];\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" : "")
394 << "void main (void)\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" : "")
400 << " gl_TessLevelInner[0] = 9.0;\n"
401 << " gl_TessLevelInner[1] = 8.0;\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"
409 programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str());
412 // Tessellation evaluation shader
414 const float xScale = 1.0f / static_cast<float>(getNumPrimitives(caseDef.caseType));
416 std::ostringstream src;
417 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
418 << "#extension GL_EXT_tessellation_shader : require\n"
420 << "layout(" << getTessPrimitiveTypeShaderName(TESSPRIMITIVETYPE_QUADS) << ") in;\n"
422 << "layout(location = 0) in highp float in_te_attr[];\n"
423 << "layout(location = 0) out mediump vec4 in_f_color;\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" : "")
428 << "void main (void)\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"
446 programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str());
451 std::ostringstream src;
452 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
454 << "layout(location = 0) in mediump vec4 in_f_color;\n"
455 << "layout(location = 0) out mediump vec4 o_color;\n"
457 << "void main (void)\n"
459 << " o_color = in_f_color;\n"
462 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
466 //! Resize an image and fill with white color.
467 void initializeWhiteReferenceImage (tcu::TextureLevel& image, const int width, const int height)
469 DE_ASSERT(width > 0 && height > 0);
471 image.setStorage(mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM), width, height);
472 tcu::PixelBufferAccess access = image.getAccess();
474 const tcu::Vec4 white(1.0f, 1.0f, 1.0f, 1.0f);
476 for (int y = 0; y < height; ++y)
477 for (int x = 0; x < width; ++x)
478 access.setPixel(white, x, y);
481 tcu::TestStatus test (Context& context, const CaseDefinition caseDef)
483 DE_ASSERT(!caseDef.usesReferenceImageFromFile || !caseDef.referenceImagePath.empty());
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();
490 for (int i = 0; i < numPrimitives; ++i)
491 vertexData[INPUT_PATCH_SIZE * i] = static_cast<float>(i) / static_cast<float>(numPrimitives);
493 tcu::TextureLevel referenceImage;
494 if (caseDef.usesReferenceImageFromFile)
495 tcu::ImageIO::loadPNG(referenceImage, context.getTestContext().getArchive(), caseDef.referenceImagePath.c_str());
497 initializeWhiteReferenceImage(referenceImage, RENDER_SIZE, RENDER_SIZE);
499 return runTest(context, numPrimitives, INPUT_PATCH_SIZE, OUTPUT_PATCH_SIZE,
500 VK_FORMAT_R32_SFLOAT, &vertexData[0], vertexBufferSize, referenceImage.getAccess());
510 CASETYPE_VS_TO_TCS = 0,
512 CASETYPE_VS_TO_TCS_TO_TES,
515 void initPrograms (vk::SourceCollections& programCollection, const CaseType caseType)
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;
522 std::ostringstream src;
523 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
525 << "layout(location = 0) in highp vec4 in_v_attr;\n"
526 << (!vsToTCS ? "layout(location = 0) out highp vec4 in_tc_attr;\n" : "")
528 << "void main (void)\n"
530 << " " << (vsToTCS ? "gl_Position" : "in_tc_attr") << " = in_v_attr;\n"
533 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
536 // Tessellation control shader
538 std::ostringstream src;
539 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
540 << "#extension GL_EXT_tessellation_shader : require\n"
542 << "layout(vertices = 3) out;\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" : "")
547 << "void main (void)\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"
552 << " gl_TessLevelInner[0] = 2.0;\n"
553 << " gl_TessLevelInner[1] = 3.0;\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"
561 programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str());
564 // Tessellation evaluation shader
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]";
570 std::ostringstream src;
571 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
572 << "#extension GL_EXT_tessellation_shader : require\n"
574 << "layout(" << getTessPrimitiveTypeShaderName(TESSPRIMITIVETYPE_TRIANGLES) << ") in;\n"
576 << (!tcsToTES ? "layout(location = 0) in highp vec4 in_te_attr[];\n" : "")
577 << "layout(location = 0) out highp vec4 in_f_color;\n"
579 << "void main (void)\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"
591 programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str());
596 std::ostringstream src;
597 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
599 << "layout(location = 0) in highp vec4 in_f_color;\n"
600 << "layout(location = 0) out mediump vec4 o_color;\n"
602 << "void main (void)\n"
604 << " o_color = in_f_color;\n"
607 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
611 tcu::TestStatus test (Context& context, const CaseType caseType)
615 // Input vertex attribute data
616 static const float vertexData[3*4] =
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
623 tcu::TextureLevel referenceImage;
624 tcu::ImageIO::loadPNG(referenceImage, context.getTestContext().getArchive(), "vulkan/data/tessellation/gl_position_ref.png");
626 const int numPrimitives = 1;
627 const int inPatchSize = 3;
628 const int outPatchSize = 3;
630 return runTest(context, numPrimitives, inPatchSize, outPatchSize,
631 VK_FORMAT_R32G32B32A32_SFLOAT, vertexData, sizeof(vertexData), referenceImage.getAccess());
644 void initPrograms (vk::SourceCollections& programCollection)
648 std::ostringstream src;
649 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
651 << "layout(location = 0) in highp float in_v_attr;\n"
652 << "layout(location = 0) out highp float in_tc_attr;\n"
654 << "void main (void)\n"
656 << " in_tc_attr = in_v_attr;\n"
659 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
662 // Tessellation control shader
664 std::ostringstream src;
665 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
666 << "#extension GL_EXT_tessellation_shader : require\n"
668 << "layout(vertices = " << NUM_VERTICES << ") out;\n"
670 << "layout(location = 0) in highp float in_tc_attr[];\n"
671 << "layout(location = 0) out highp float in_te_attr[];\n"
673 << "layout(location = 1) patch out highp float in_te_patchAttr;\n"
675 << "void main (void)\n"
677 << " in_te_attr[gl_InvocationID] = in_tc_attr[gl_InvocationID];\n"
678 << " in_te_patchAttr = 0.0f;\n"
682 << " if (gl_InvocationID == 5)\n"
683 << " in_te_patchAttr = float(gl_InvocationID)*0.1;\n"
687 << " highp float temp = in_te_patchAttr + in_te_attr[gl_InvocationID];\n"
691 << " if (gl_InvocationID == " << NUM_VERTICES << "-1)\n"
692 << " in_te_patchAttr = float(gl_InvocationID);\n"
696 << " in_te_attr[gl_InvocationID] = temp;\n"
700 << " temp = temp + in_te_attr[(gl_InvocationID+1) % " << NUM_VERTICES << "];\n"
704 << " in_te_attr[gl_InvocationID] = 0.25*temp;\n"
706 << " gl_TessLevelInner[0] = 32.0;\n"
707 << " gl_TessLevelInner[1] = 32.0;\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"
715 programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str());
718 // Tessellation evaluation shader
720 std::ostringstream src;
721 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
722 << "#extension GL_EXT_tessellation_shader : require\n"
724 << "layout(" << getTessPrimitiveTypeShaderName(TESSPRIMITIVETYPE_QUADS) << ") in;\n"
726 << "layout(location = 0) in highp float in_te_attr[];\n"
727 << "layout(location = 1) patch in highp float in_te_patchAttr;\n"
729 << "layout(location = 0) out highp float in_f_blue;\n"
731 << "void main (void)\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"
739 programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str());
744 std::ostringstream src;
745 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
747 << "layout(location = 0) in highp float in_f_blue;\n"
748 << "layout(location = 0) out mediump vec4 o_color;\n"
750 << "void main (void)\n"
752 << " o_color = vec4(1.0, 0.0, in_f_blue, 1.0);\n"
755 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
759 tcu::TestStatus test (Context& context)
761 // Input vertex attribute data
762 std::vector<float> vertexData (NUM_VERTICES);
763 const VkDeviceSize vertexBufferSize = sizeof(float) * vertexData.size();
765 for (int i = 0; i < NUM_VERTICES; ++i)
766 vertexData[i] = static_cast<float>(i) / (NUM_VERTICES - 1);
768 tcu::TextureLevel referenceImage;
769 tcu::ImageIO::loadPNG(referenceImage, context.getTestContext().getArchive(), "vulkan/data/tessellation/barrier_ref.png");
771 const int numPrimitives = 1;
772 const int inPatchSize = NUM_VERTICES;
773 const int outPatchSize = NUM_VERTICES;
775 return runTest(context, numPrimitives, inPatchSize, outPatchSize,
776 VK_FORMAT_R32_SFLOAT, &vertexData[0], vertexBufferSize, referenceImage.getAccess());
783 //! These tests correspond to dEQP-GLES31.functional.tessellation.shader_input_output.*
784 tcu::TestCaseGroup* createShaderInputOutputTests (tcu::TestContext& testCtx)
786 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "shader_input_output", "Test tessellation control and evaluation shader inputs and outputs"));
788 // Patch vertex counts
794 } patchVertexCountCases[] =
800 for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(patchVertexCountCases); caseNdx++)
802 const int inSize = patchVertexCountCases[caseNdx].inPatchSize;
803 const int outSize = patchVertexCountCases[caseNdx].outPatchSize;
805 const std::string caseName = "patch_vertices_" + de::toString(inSize) + "_in_" + de::toString(outSize) + "_out";
806 const PatchVertexCount::CaseDefinition caseDef =
808 inSize, outSize, "vulkan/data/tessellation/" + caseName + "_ref.png"
811 addFunctionCaseWithPrograms(group.get(), caseName, "Test input and output patch vertex counts",
812 PatchVertexCount::initPrograms, PatchVertexCount::test, caseDef);
818 static const PerPatchData::CaseDefinition cases[] =
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" },
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]);
841 GLPosition::CaseType type;
842 std::string caseName;
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" },
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);
856 addFunctionCaseWithPrograms(group.get(), "barrier", "Basic barrier usage", Barrier::initPrograms, Barrier::test);
858 return group.release();