| /*------------------------------------------------------------------------ |
| * Vulkan Conformance Tests |
| * ------------------------ |
| * |
| * Copyright (c) 2014 The Android Open Source Project |
| * Copyright (c) 2016 The Khronos Group Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| *//*! |
| * \file |
| * \brief Tessellation Shader Input/Output Tests |
| *//*--------------------------------------------------------------------*/ |
| |
| #include "vktTessellationShaderInputOutputTests.hpp" |
| #include "vktTestCaseUtil.hpp" |
| #include "vktTessellationUtil.hpp" |
| |
| #include "tcuTestLog.hpp" |
| #include "tcuImageIO.hpp" |
| #include "tcuTexture.hpp" |
| #include "tcuImageCompare.hpp" |
| |
| #include "vkDefs.hpp" |
| #include "vkBarrierUtil.hpp" |
| #include "vkQueryUtil.hpp" |
| #include "vkBuilderUtil.hpp" |
| #include "vkImageUtil.hpp" |
| #include "vkTypeUtil.hpp" |
| #include "vkStrUtil.hpp" |
| #include "vkCmdUtil.hpp" |
| #include "vkObjUtil.hpp" |
| |
| #include "deUniquePtr.hpp" |
| #include "deStringUtil.hpp" |
| |
| #include <string> |
| #include <vector> |
| |
| namespace vkt |
| { |
| namespace tessellation |
| { |
| |
| using namespace vk; |
| |
| namespace |
| { |
| |
| enum Constants |
| { |
| RENDER_SIZE = 256, |
| }; |
| |
| //! Generic test code used by all test cases. |
| tcu::TestStatus 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) |
| { |
| requireFeatures(context.getInstanceInterface(), context.getPhysicalDevice(), FEATURE_TESSELLATION_SHADER); |
| |
| const DeviceInterface& vk = context.getDeviceInterface(); |
| const VkDevice device = context.getDevice(); |
| const VkQueue queue = context.getUniversalQueue(); |
| const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); |
| Allocator& allocator = context.getDefaultAllocator(); |
| |
| // Vertex input: may be just some abstract numbers |
| |
| const Buffer vertexBuffer(vk, device, allocator, |
| makeBufferCreateInfo(vertexDataSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), MemoryRequirement::HostVisible); |
| |
| { |
| const Allocation& alloc = vertexBuffer.getAllocation(); |
| |
| deMemcpy(alloc.getHostPtr(), vertexData, static_cast<std::size_t>(vertexDataSizeBytes)); |
| flushAlloc(vk, device, alloc); |
| // No barrier needed, flushed memory is automatically visible |
| } |
| |
| // Color attachment |
| |
| const tcu::IVec2 renderSize = tcu::IVec2(RENDER_SIZE, RENDER_SIZE); |
| const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM; |
| const VkImageSubresourceRange colorImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u); |
| const Image colorAttachmentImage (vk, device, allocator, |
| makeImageCreateInfo(renderSize, colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 1u), |
| MemoryRequirement::Any); |
| |
| // Color output buffer: image will be copied here for verification |
| |
| const VkDeviceSize colorBufferSizeBytes = renderSize.x()*renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat)); |
| const Buffer colorBuffer (vk, device, allocator, makeBufferCreateInfo(colorBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT), MemoryRequirement::HostVisible); |
| |
| // Pipeline |
| |
| const Unique<VkImageView> colorAttachmentView (makeImageView (vk, device, *colorAttachmentImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorImageSubresourceRange)); |
| const Unique<VkRenderPass> renderPass (makeRenderPass (vk, device, colorFormat)); |
| const Unique<VkFramebuffer> framebuffer (makeFramebuffer (vk, device, *renderPass, *colorAttachmentView, renderSize.x(), renderSize.y())); |
| const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout (vk, device)); |
| const Unique<VkCommandPool> cmdPool (makeCommandPool (vk, device, queueFamilyIndex)); |
| const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY)); |
| |
| const Unique<VkPipeline> pipeline(GraphicsPipelineBuilder() |
| .setRenderSize (renderSize) |
| .setVertexInputSingleAttribute(vertexFormat, tcu::getPixelSize(mapVkFormat(vertexFormat))) |
| .setPatchControlPoints (inPatchSize) |
| .setShader (vk, device, VK_SHADER_STAGE_VERTEX_BIT, context.getBinaryCollection().get("vert"), DE_NULL) |
| .setShader (vk, device, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, context.getBinaryCollection().get("tesc"), DE_NULL) |
| .setShader (vk, device, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, context.getBinaryCollection().get("tese"), DE_NULL) |
| .setShader (vk, device, VK_SHADER_STAGE_FRAGMENT_BIT, context.getBinaryCollection().get("frag"), DE_NULL) |
| .build (vk, device, *pipelineLayout, *renderPass)); |
| |
| { |
| tcu::TestLog& log = context.getTestContext().getLog(); |
| log << tcu::TestLog::Message |
| << "Note: input patch size is " << inPatchSize << ", output patch size is " << outPatchSize |
| << tcu::TestLog::EndMessage; |
| } |
| |
| // Draw commands |
| |
| beginCommandBuffer(vk, *cmdBuffer); |
| |
| // Change color attachment image layout |
| { |
| const VkImageMemoryBarrier colorAttachmentLayoutBarrier = makeImageMemoryBarrier( |
| (VkAccessFlags)0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, |
| VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, |
| *colorAttachmentImage, colorImageSubresourceRange); |
| |
| vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, |
| 0u, DE_NULL, 0u, DE_NULL, 1u, &colorAttachmentLayoutBarrier); |
| } |
| |
| // Begin render pass |
| { |
| const VkRect2D renderArea = makeRect2D(renderSize); |
| const tcu::Vec4 clearColor (0.0f, 0.0f, 0.0f, 1.0f); |
| |
| beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea, clearColor); |
| } |
| |
| vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline); |
| { |
| const VkDeviceSize vertexBufferOffset = 0ull; |
| vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset); |
| } |
| |
| // Process enough vertices to make a patch. |
| vk.cmdDraw(*cmdBuffer, numPrimitives * inPatchSize, 1u, 0u, 0u); |
| endRenderPass(vk, *cmdBuffer); |
| |
| // Copy render result to a host-visible buffer |
| copyImageToBuffer(vk, *cmdBuffer, *colorAttachmentImage, *colorBuffer, renderSize); |
| |
| endCommandBuffer(vk, *cmdBuffer); |
| submitCommandsAndWait(vk, device, queue, *cmdBuffer); |
| |
| { |
| const Allocation& colorBufferAlloc = colorBuffer.getAllocation(); |
| |
| invalidateAlloc(vk, device, colorBufferAlloc); |
| |
| // Verify case result |
| const tcu::ConstPixelBufferAccess resultImageAccess (mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1, colorBufferAlloc.getHostPtr()); |
| tcu::TestLog& log = context.getTestContext().getLog(); |
| const bool ok = tcu::fuzzyCompare(log, "ImageComparison", "Image Comparison", referenceImageAccess, resultImageAccess, |
| 0.002f, tcu::COMPARE_LOG_RESULT); |
| |
| return (ok ? tcu::TestStatus::pass("OK") : tcu::TestStatus::fail("Failure")); |
| } |
| } |
| |
| //! Resize an image and fill with white color. |
| void initializeWhiteReferenceImage (tcu::TextureLevel& image, const int width, const int height) |
| { |
| DE_ASSERT(width > 0 && height > 0); |
| |
| image.setStorage(mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM), width, height); |
| tcu::PixelBufferAccess access = image.getAccess(); |
| |
| const tcu::Vec4 white(1.0f, 1.0f, 1.0f, 1.0f); |
| |
| for (int y = 0; y < height; ++y) |
| for (int x = 0; x < width; ++x) |
| access.setPixel(white, x, y); |
| } |
| |
| namespace PatchVertexCount |
| { |
| |
| struct CaseDefinition |
| { |
| int inPatchSize; |
| int outPatchSize; |
| std::string referenceImagePath; |
| }; |
| |
| void initPrograms (vk::SourceCollections& programCollection, const CaseDefinition caseDef) |
| { |
| // Vertex shader |
| { |
| std::ostringstream src; |
| src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n" |
| << "\n" |
| << "layout(location = 0) in highp float in_v_attr;\n" |
| << "layout(location = 0) out highp float in_tc_attr;\n" |
| << "\n" |
| << "void main (void)\n" |
| << "{\n" |
| << " in_tc_attr = in_v_attr;\n" |
| << "}\n"; |
| |
| programCollection.glslSources.add("vert") << glu::VertexSource(src.str()); |
| } |
| |
| // Tessellation control shader |
| { |
| std::ostringstream src; |
| src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n" |
| << "#extension GL_EXT_tessellation_shader : require\n" |
| << "\n" |
| << "layout(vertices = " << caseDef.outPatchSize << ") out;\n" |
| << "\n" |
| << "layout(location = 0) in highp float in_tc_attr[];\n" |
| << "layout(location = 0) out highp float in_te_attr[];\n" |
| << "\n" |
| << "void main (void)\n" |
| << "{\n" |
| << " in_te_attr[gl_InvocationID] = in_tc_attr[gl_InvocationID*" << caseDef.inPatchSize << "/" << caseDef.outPatchSize << "];\n" |
| << "\n" |
| << " gl_TessLevelInner[0] = 5.0;\n" |
| << " gl_TessLevelInner[1] = 5.0;\n" |
| << "\n" |
| << " gl_TessLevelOuter[0] = 5.0;\n" |
| << " gl_TessLevelOuter[1] = 5.0;\n" |
| << " gl_TessLevelOuter[2] = 5.0;\n" |
| << " gl_TessLevelOuter[3] = 5.0;\n" |
| << "}\n"; |
| |
| programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str()); |
| } |
| |
| // Tessellation evaluation shader |
| { |
| std::ostringstream src; |
| src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n" |
| << "#extension GL_EXT_tessellation_shader : require\n" |
| << "\n" |
| << "layout(" << getTessPrimitiveTypeShaderName(TESSPRIMITIVETYPE_QUADS) << ") in;\n" |
| << "\n" |
| << "layout(location = 0) in highp float in_te_attr[];\n" |
| << "layout(location = 0) out mediump vec4 in_f_color;\n" |
| << "\n" |
| << "void main (void)\n" |
| << "{\n" |
| << " highp float x = gl_TessCoord.x*2.0 - 1.0;\n" |
| << " highp float y = gl_TessCoord.y - in_te_attr[int(round(gl_TessCoord.x*float(" << caseDef.outPatchSize << "-1)))];\n" |
| << " gl_Position = vec4(x, y, 0.0, 1.0);\n" |
| << " in_f_color = vec4(1.0);\n" |
| << "}\n"; |
| |
| programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str()); |
| } |
| |
| // Fragment shader |
| { |
| std::ostringstream src; |
| src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n" |
| << "\n" |
| << "layout(location = 0) in mediump vec4 in_f_color;\n" |
| << "layout(location = 0) out mediump vec4 o_color;\n" |
| << "\n" |
| << "void main (void)\n" |
| << "{\n" |
| << " o_color = in_f_color;\n" |
| << "}\n"; |
| |
| programCollection.glslSources.add("frag") << glu::FragmentSource(src.str()); |
| } |
| } |
| |
| tcu::TestStatus test (Context& context, const CaseDefinition caseDef) |
| { |
| // Input vertex attribute data |
| std::vector<float> vertexData; |
| vertexData.reserve(caseDef.inPatchSize); |
| for (int i = 0; i < caseDef.inPatchSize; ++i) |
| { |
| const float f = static_cast<float>(i) / static_cast<float>(caseDef.inPatchSize - 1); |
| vertexData.push_back(f*f); |
| } |
| const VkDeviceSize vertexBufferSize = sizeof(float) * vertexData.size(); |
| |
| // Load reference image |
| tcu::TextureLevel referenceImage; |
| tcu::ImageIO::loadPNG(referenceImage, context.getTestContext().getArchive(), caseDef.referenceImagePath.c_str()); |
| |
| const int numPrimitives = 1; |
| |
| return runTest(context, numPrimitives, caseDef.inPatchSize, caseDef.outPatchSize, |
| VK_FORMAT_R32_SFLOAT, &vertexData[0], vertexBufferSize, referenceImage.getAccess()); |
| } |
| |
| } // PatchVertexCountTest ns |
| |
| namespace PerPatchData |
| { |
| |
| enum CaseType |
| { |
| CASETYPE_PRIMITIVE_ID_TCS, |
| CASETYPE_PRIMITIVE_ID_TES, |
| CASETYPE_PATCH_VERTICES_IN_TCS, |
| CASETYPE_PATCH_VERTICES_IN_TES, |
| CASETYPE_TESS_LEVEL_INNER0_TES, |
| CASETYPE_TESS_LEVEL_INNER1_TES, |
| CASETYPE_TESS_LEVEL_OUTER0_TES, |
| CASETYPE_TESS_LEVEL_OUTER1_TES, |
| CASETYPE_TESS_LEVEL_OUTER2_TES, |
| CASETYPE_TESS_LEVEL_OUTER3_TES, |
| }; |
| |
| enum Constants |
| { |
| OUTPUT_PATCH_SIZE = 5, |
| INPUT_PATCH_SIZE = 10, |
| }; |
| |
| struct CaseDefinition |
| { |
| CaseType caseType; |
| std::string caseName; |
| bool usesReferenceImageFromFile; |
| std::string referenceImagePath; |
| std::string caseDescription; |
| }; |
| |
| int getNumPrimitives (const CaseType type) |
| { |
| return (type == CASETYPE_PRIMITIVE_ID_TCS || type == CASETYPE_PRIMITIVE_ID_TES ? 8 : 1); |
| } |
| |
| void initPrograms (vk::SourceCollections& programCollection, const CaseDefinition caseDef) |
| { |
| // Vertex shader |
| { |
| std::ostringstream src; |
| src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n" |
| << "\n" |
| << "layout(location = 0) in highp float in_v_attr;\n" |
| << "layout(location = 0) out highp float in_tc_attr;\n" |
| << "\n" |
| << "void main (void)\n" |
| << "{\n" |
| << " in_tc_attr = in_v_attr;\n" |
| << "}\n"; |
| |
| programCollection.glslSources.add("vert") << glu::VertexSource(src.str()); |
| } |
| |
| // Tessellation control shader |
| { |
| std::ostringstream src; |
| src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n" |
| << "#extension GL_EXT_tessellation_shader : require\n" |
| << "\n" |
| << "layout(vertices = " << OUTPUT_PATCH_SIZE << ") out;\n" |
| << "\n" |
| << "layout(location = 0) in highp float in_tc_attr[];\n" |
| << "layout(location = 0) out highp float in_te_attr[];\n" |
| << "\n" |
| << (caseDef.caseType == CASETYPE_PRIMITIVE_ID_TCS ? "layout(location = 1) patch out mediump int in_te_primitiveIDFromTCS;\n" : |
| caseDef.caseType == CASETYPE_PATCH_VERTICES_IN_TCS ? "layout(location = 1) patch out mediump int in_te_patchVerticesInFromTCS;\n" : "") |
| << "\n" |
| << "void main (void)\n" |
| << "{\n" |
| << " in_te_attr[gl_InvocationID] = in_tc_attr[gl_InvocationID];\n" |
| << (caseDef.caseType == CASETYPE_PRIMITIVE_ID_TCS ? " in_te_primitiveIDFromTCS = gl_PrimitiveID;\n" : |
| caseDef.caseType == CASETYPE_PATCH_VERTICES_IN_TCS ? " in_te_patchVerticesInFromTCS = gl_PatchVerticesIn;\n" : "") |
| << "\n" |
| << " gl_TessLevelInner[0] = 9.0;\n" |
| << " gl_TessLevelInner[1] = 8.0;\n" |
| << "\n" |
| << " gl_TessLevelOuter[0] = 7.0;\n" |
| << " gl_TessLevelOuter[1] = 6.0;\n" |
| << " gl_TessLevelOuter[2] = 5.0;\n" |
| << " gl_TessLevelOuter[3] = 4.0;\n" |
| << "}\n"; |
| |
| programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str()); |
| } |
| |
| // Tessellation evaluation shader |
| { |
| const float xScale = 1.0f / static_cast<float>(getNumPrimitives(caseDef.caseType)); |
| |
| std::ostringstream src; |
| src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n" |
| << "#extension GL_EXT_tessellation_shader : require\n" |
| << "\n" |
| << "layout(" << getTessPrimitiveTypeShaderName(TESSPRIMITIVETYPE_QUADS) << ") in;\n" |
| << "\n" |
| << "layout(location = 0) in highp float in_te_attr[];\n" |
| << "layout(location = 0) out mediump vec4 in_f_color;\n" |
| << "\n" |
| << (caseDef.caseType == CASETYPE_PRIMITIVE_ID_TCS ? "layout(location = 1) patch in mediump int in_te_primitiveIDFromTCS;\n" : |
| caseDef.caseType == CASETYPE_PATCH_VERTICES_IN_TCS ? "layout(location = 1) patch in mediump int in_te_patchVerticesInFromTCS;\n" : "") |
| << "\n" |
| << "void main (void)\n" |
| << "{\n" |
| << " highp float x = (gl_TessCoord.x*float(" << xScale << ") + in_te_attr[0]) * 2.0 - 1.0;\n" |
| << " highp float y = gl_TessCoord.y*2.0 - 1.0;\n" |
| << " gl_Position = vec4(x, y, 0.0, 1.0);\n" |
| << (caseDef.caseType == CASETYPE_PRIMITIVE_ID_TCS ? " bool ok = in_te_primitiveIDFromTCS == 3;\n" : |
| caseDef.caseType == CASETYPE_PRIMITIVE_ID_TES ? " bool ok = gl_PrimitiveID == 3;\n" : |
| caseDef.caseType == CASETYPE_PATCH_VERTICES_IN_TCS ? " bool ok = in_te_patchVerticesInFromTCS == " + de::toString(INPUT_PATCH_SIZE) + ";\n" : |
| caseDef.caseType == CASETYPE_PATCH_VERTICES_IN_TES ? " bool ok = gl_PatchVerticesIn == " + de::toString(OUTPUT_PATCH_SIZE) + ";\n" : |
| caseDef.caseType == CASETYPE_TESS_LEVEL_INNER0_TES ? " bool ok = abs(gl_TessLevelInner[0] - 9.0) < 0.1f;\n" : |
| caseDef.caseType == CASETYPE_TESS_LEVEL_INNER1_TES ? " bool ok = abs(gl_TessLevelInner[1] - 8.0) < 0.1f;\n" : |
| caseDef.caseType == CASETYPE_TESS_LEVEL_OUTER0_TES ? " bool ok = abs(gl_TessLevelOuter[0] - 7.0) < 0.1f;\n" : |
| caseDef.caseType == CASETYPE_TESS_LEVEL_OUTER1_TES ? " bool ok = abs(gl_TessLevelOuter[1] - 6.0) < 0.1f;\n" : |
| caseDef.caseType == CASETYPE_TESS_LEVEL_OUTER2_TES ? " bool ok = abs(gl_TessLevelOuter[2] - 5.0) < 0.1f;\n" : |
| caseDef.caseType == CASETYPE_TESS_LEVEL_OUTER3_TES ? " bool ok = abs(gl_TessLevelOuter[3] - 4.0) < 0.1f;\n" : "") |
| << " in_f_color = ok ? vec4(1.0) : vec4(vec3(0.0), 1.0);\n" |
| << "}\n"; |
| |
| programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str()); |
| } |
| |
| // Fragment shader |
| { |
| std::ostringstream src; |
| src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n" |
| << "\n" |
| << "layout(location = 0) in mediump vec4 in_f_color;\n" |
| << "layout(location = 0) out mediump vec4 o_color;\n" |
| << "\n" |
| << "void main (void)\n" |
| << "{\n" |
| << " o_color = in_f_color;\n" |
| << "}\n"; |
| |
| programCollection.glslSources.add("frag") << glu::FragmentSource(src.str()); |
| } |
| } |
| |
| tcu::TestStatus test (Context& context, const CaseDefinition caseDef) |
| { |
| DE_ASSERT(!caseDef.usesReferenceImageFromFile || !caseDef.referenceImagePath.empty()); |
| |
| // Input vertex attribute data |
| const int numPrimitives = getNumPrimitives(caseDef.caseType); |
| std::vector<float> vertexData (INPUT_PATCH_SIZE * numPrimitives, 0.0f); |
| const VkDeviceSize vertexBufferSize = sizeof(float) * vertexData.size(); |
| |
| for (int i = 0; i < numPrimitives; ++i) |
| vertexData[INPUT_PATCH_SIZE * i] = static_cast<float>(i) / static_cast<float>(numPrimitives); |
| |
| tcu::TextureLevel referenceImage; |
| if (caseDef.usesReferenceImageFromFile) |
| tcu::ImageIO::loadPNG(referenceImage, context.getTestContext().getArchive(), caseDef.referenceImagePath.c_str()); |
| else |
| initializeWhiteReferenceImage(referenceImage, RENDER_SIZE, RENDER_SIZE); |
| |
| return runTest(context, numPrimitives, INPUT_PATCH_SIZE, OUTPUT_PATCH_SIZE, |
| VK_FORMAT_R32_SFLOAT, &vertexData[0], vertexBufferSize, referenceImage.getAccess()); |
| } |
| |
| } // PerPatchData ns |
| |
| namespace GLPosition |
| { |
| |
| enum CaseType |
| { |
| CASETYPE_VS_TO_TCS = 0, |
| CASETYPE_TCS_TO_TES, |
| CASETYPE_VS_TO_TCS_TO_TES, |
| }; |
| |
| void initPrograms (vk::SourceCollections& programCollection, const CaseType caseType) |
| { |
| const bool vsToTCS = caseType == CASETYPE_VS_TO_TCS || caseType == CASETYPE_VS_TO_TCS_TO_TES; |
| const bool tcsToTES = caseType == CASETYPE_TCS_TO_TES || caseType == CASETYPE_VS_TO_TCS_TO_TES; |
| |
| // Vertex shader |
| { |
| std::ostringstream src; |
| src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n" |
| << "\n" |
| << "layout(location = 0) in highp vec4 in_v_attr;\n" |
| << (!vsToTCS ? "layout(location = 0) out highp vec4 in_tc_attr;\n" : "") |
| << "\n" |
| << "void main (void)\n" |
| << "{\n" |
| << " " << (vsToTCS ? "gl_Position" : "in_tc_attr") << " = in_v_attr;\n" |
| << "}\n"; |
| |
| programCollection.glslSources.add("vert") << glu::VertexSource(src.str()); |
| } |
| |
| // Tessellation control shader |
| { |
| std::ostringstream src; |
| src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n" |
| << "#extension GL_EXT_tessellation_shader : require\n" |
| << "\n" |
| << "layout(vertices = 3) out;\n" |
| << "\n" |
| << (!vsToTCS ? "layout(location = 0) in highp vec4 in_tc_attr[];\n" : "") |
| << (!tcsToTES ? "layout(location = 0) out highp vec4 in_te_attr[];\n" : "") |
| << "\n" |
| << "void main (void)\n" |
| << "{\n" |
| << " " << (tcsToTES ? "gl_out[gl_InvocationID].gl_Position" : "in_te_attr[gl_InvocationID]") << " = " |
| << (vsToTCS ? "gl_in[gl_InvocationID].gl_Position" : "in_tc_attr[gl_InvocationID]") << ";\n" |
| << "\n" |
| << " gl_TessLevelInner[0] = 2.0;\n" |
| << " gl_TessLevelInner[1] = 3.0;\n" |
| << "\n" |
| << " gl_TessLevelOuter[0] = 4.0;\n" |
| << " gl_TessLevelOuter[1] = 5.0;\n" |
| << " gl_TessLevelOuter[2] = 6.0;\n" |
| << " gl_TessLevelOuter[3] = 7.0;\n" |
| << "}\n"; |
| |
| programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str()); |
| } |
| |
| // Tessellation evaluation shader |
| { |
| const std::string tesIn0 = tcsToTES ? "gl_in[0].gl_Position" : "in_te_attr[0]"; |
| const std::string tesIn1 = tcsToTES ? "gl_in[1].gl_Position" : "in_te_attr[1]"; |
| const std::string tesIn2 = tcsToTES ? "gl_in[2].gl_Position" : "in_te_attr[2]"; |
| |
| std::ostringstream src; |
| src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n" |
| << "#extension GL_EXT_tessellation_shader : require\n" |
| << "\n" |
| << "layout(" << getTessPrimitiveTypeShaderName(TESSPRIMITIVETYPE_TRIANGLES) << ") in;\n" |
| << "\n" |
| << (!tcsToTES ? "layout(location = 0) in highp vec4 in_te_attr[];\n" : "") |
| << "layout(location = 0) out highp vec4 in_f_color;\n" |
| << "\n" |
| << "void main (void)\n" |
| << "{\n" |
| << " highp vec2 xy = gl_TessCoord.x * " << tesIn0 << ".xy\n" |
| << " + gl_TessCoord.y * " << tesIn1 << ".xy\n" |
| << " + gl_TessCoord.z * " << tesIn2 << ".xy;\n" |
| << " gl_Position = vec4(xy, 0.0, 1.0);\n" |
| << " in_f_color = vec4(" << tesIn0 << ".z + " << tesIn1 << ".w,\n" |
| << " " << tesIn2 << ".z + " << tesIn0 << ".w,\n" |
| << " " << tesIn1 << ".z + " << tesIn2 << ".w,\n" |
| << " 1.0);\n" |
| << "}\n"; |
| |
| programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str()); |
| } |
| |
| // Fragment shader |
| { |
| std::ostringstream src; |
| src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n" |
| << "\n" |
| << "layout(location = 0) in highp vec4 in_f_color;\n" |
| << "layout(location = 0) out mediump vec4 o_color;\n" |
| << "\n" |
| << "void main (void)\n" |
| << "{\n" |
| << " o_color = in_f_color;\n" |
| << "}\n"; |
| |
| programCollection.glslSources.add("frag") << glu::FragmentSource(src.str()); |
| } |
| } |
| |
| tcu::TestStatus test (Context& context, const CaseType caseType) |
| { |
| DE_UNREF(caseType); |
| |
| // Input vertex attribute data |
| static const float vertexData[3*4] = |
| { |
| -0.8f, -0.7f, 0.1f, 0.7f, |
| -0.5f, 0.4f, 0.2f, 0.5f, |
| 0.3f, 0.2f, 0.3f, 0.45f |
| }; |
| |
| tcu::TextureLevel referenceImage; |
| tcu::ImageIO::loadPNG(referenceImage, context.getTestContext().getArchive(), "vulkan/data/tessellation/gl_position_ref.png"); |
| |
| const int numPrimitives = 1; |
| const int inPatchSize = 3; |
| const int outPatchSize = 3; |
| |
| return runTest(context, numPrimitives, inPatchSize, outPatchSize, |
| VK_FORMAT_R32G32B32A32_SFLOAT, vertexData, sizeof(vertexData), referenceImage.getAccess()); |
| } |
| |
| } // GLPosition ns |
| |
| namespace Barrier |
| { |
| |
| enum Constants |
| { |
| NUM_VERTICES = 32, |
| }; |
| |
| void initPrograms (vk::SourceCollections& programCollection) |
| { |
| // Vertex shader |
| { |
| std::ostringstream src; |
| src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n" |
| << "\n" |
| << "layout(location = 0) in highp float in_v_attr;\n" |
| << "layout(location = 0) out highp float in_tc_attr;\n" |
| << "\n" |
| << "void main (void)\n" |
| << "{\n" |
| << " in_tc_attr = in_v_attr;\n" |
| << "}\n"; |
| |
| programCollection.glslSources.add("vert") << glu::VertexSource(src.str()); |
| } |
| |
| // Tessellation control shader |
| { |
| std::ostringstream src; |
| src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n" |
| << "#extension GL_EXT_tessellation_shader : require\n" |
| << "\n" |
| << "layout(vertices = " << NUM_VERTICES << ") out;\n" |
| << "\n" |
| << "layout(location = 0) in highp float in_tc_attr[];\n" |
| << "layout(location = 0) out highp float in_te_attr[];\n" |
| << "\n" |
| << "layout(location = 1) patch out highp float in_te_patchAttr;\n" |
| << "\n" |
| << "void main (void)\n" |
| << "{\n" |
| << " in_te_attr[gl_InvocationID] = in_tc_attr[gl_InvocationID];\n" |
| << " in_te_patchAttr = 0.0f;\n" |
| << "\n" |
| << " barrier();\n" |
| << "\n" |
| << " if (gl_InvocationID == 5)\n" |
| << " in_te_patchAttr = float(gl_InvocationID)*0.1;\n" |
| << "\n" |
| << " barrier();\n" |
| << "\n" |
| << " highp float temp = in_te_patchAttr + in_te_attr[gl_InvocationID];\n" |
| << "\n" |
| << " barrier();\n" |
| << "\n" |
| << " if (gl_InvocationID == " << NUM_VERTICES << "-1)\n" |
| << " in_te_patchAttr = float(gl_InvocationID);\n" |
| << "\n" |
| << " barrier();\n" |
| << "\n" |
| << " in_te_attr[gl_InvocationID] = temp;\n" |
| << "\n" |
| << " barrier();\n" |
| << "\n" |
| << " temp = temp + in_te_attr[(gl_InvocationID+1) % " << NUM_VERTICES << "];\n" |
| << "\n" |
| << " barrier();\n" |
| << "\n" |
| << " in_te_attr[gl_InvocationID] = 0.25*temp;\n" |
| << "\n" |
| << " gl_TessLevelInner[0] = 32.0;\n" |
| << " gl_TessLevelInner[1] = 32.0;\n" |
| << "\n" |
| << " gl_TessLevelOuter[0] = 32.0;\n" |
| << " gl_TessLevelOuter[1] = 32.0;\n" |
| << " gl_TessLevelOuter[2] = 32.0;\n" |
| << " gl_TessLevelOuter[3] = 32.0;\n" |
| << "}\n"; |
| |
| programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str()); |
| } |
| |
| // Tessellation evaluation shader |
| { |
| std::ostringstream src; |
| src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n" |
| << "#extension GL_EXT_tessellation_shader : require\n" |
| << "\n" |
| << "layout(" << getTessPrimitiveTypeShaderName(TESSPRIMITIVETYPE_QUADS) << ") in;\n" |
| << "\n" |
| << "layout(location = 0) in highp float in_te_attr[];\n" |
| << "layout(location = 1) patch in highp float in_te_patchAttr;\n" |
| << "\n" |
| << "layout(location = 0) out highp float in_f_blue;\n" |
| << "\n" |
| << "void main (void)\n" |
| << "{\n" |
| << " highp float x = gl_TessCoord.x*2.0 - 1.0;\n" |
| << " highp float y = gl_TessCoord.y - in_te_attr[int(round(gl_TessCoord.x*float(" << NUM_VERTICES << "-1)))];\n" |
| << " gl_Position = vec4(x, y, 0.0, 1.0);\n" |
| << " in_f_blue = abs(in_te_patchAttr - float(" << NUM_VERTICES << "-1));\n" |
| << "}\n"; |
| |
| programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str()); |
| } |
| |
| // Fragment shader |
| { |
| std::ostringstream src; |
| src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n" |
| << "\n" |
| << "layout(location = 0) in highp float in_f_blue;\n" |
| << "layout(location = 0) out mediump vec4 o_color;\n" |
| << "\n" |
| << "void main (void)\n" |
| << "{\n" |
| << " o_color = vec4(1.0, 0.0, in_f_blue, 1.0);\n" |
| << "}\n"; |
| |
| programCollection.glslSources.add("frag") << glu::FragmentSource(src.str()); |
| } |
| } |
| |
| tcu::TestStatus test (Context& context) |
| { |
| // Input vertex attribute data |
| std::vector<float> vertexData (NUM_VERTICES); |
| const VkDeviceSize vertexBufferSize = sizeof(float) * vertexData.size(); |
| |
| for (int i = 0; i < NUM_VERTICES; ++i) |
| vertexData[i] = static_cast<float>(i) / (NUM_VERTICES - 1); |
| |
| tcu::TextureLevel referenceImage; |
| tcu::ImageIO::loadPNG(referenceImage, context.getTestContext().getArchive(), "vulkan/data/tessellation/barrier_ref.png"); |
| |
| const int numPrimitives = 1; |
| const int inPatchSize = NUM_VERTICES; |
| const int outPatchSize = NUM_VERTICES; |
| |
| return runTest(context, numPrimitives, inPatchSize, outPatchSize, |
| VK_FORMAT_R32_SFLOAT, &vertexData[0], vertexBufferSize, referenceImage.getAccess()); |
| } |
| |
| } // Barrier ns |
| |
| namespace CrossInvocation |
| { |
| |
| enum Constants |
| { |
| OUTPUT_PATCH_SIZE = 3, |
| INPUT_PATCH_SIZE = 10 |
| }; |
| |
| enum CaseType |
| { |
| CASETYPE_PER_VERTEX, |
| CASETYPE_PER_PATCH |
| }; |
| |
| enum DataType |
| { |
| DATATYPE_INT, |
| DATATYPE_UINT, |
| DATATYPE_FLOAT, |
| DATATYPE_VEC3, |
| DATATYPE_VEC4, |
| DATATYPE_MAT4X3 |
| }; |
| |
| struct CaseDefinition |
| { |
| CaseType caseType; |
| DataType dataType; |
| }; |
| |
| void initPrograms (vk::SourceCollections& programCollection, const CaseDefinition caseDef) |
| { |
| static const std::string typeStr[] = |
| { |
| "int", |
| "uint", |
| "float", |
| "vec3", |
| "vec4", |
| "mat4x3" |
| }; |
| const std::string dataType = typeStr[caseDef.dataType]; |
| const int varyingSize[] = { 1, 1, 1, 1, 1, 4 }; |
| |
| // Vertex shader |
| { |
| std::ostringstream src; |
| src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n" |
| << "\n" |
| << "layout(location = 0) in highp float in_v_attr;\n" |
| << "layout(location = 0) out highp float in_tc_attr;\n" |
| << "\n" |
| << "void main (void)\n" |
| << "{\n" |
| << " in_tc_attr = in_v_attr;\n" |
| << "}\n"; |
| |
| programCollection.glslSources.add("vert") << glu::VertexSource(src.str()); |
| } |
| |
| // Tessellation control shader |
| { |
| std::ostringstream src; |
| src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n" |
| << "#extension GL_EXT_tessellation_shader : require\n" |
| << "\n" |
| << "layout(vertices = " << OUTPUT_PATCH_SIZE << ") out;\n" |
| << "\n" |
| << "layout(location = 0) in highp float in_tc_attr[];\n" |
| << "layout(location = 0) out highp float in_te_attr[];\n" |
| << "\n"; |
| |
| if (caseDef.caseType == CASETYPE_PER_VERTEX) |
| src << "layout(location = 1) out mediump " << dataType << " in_te_data0[];\n" |
| << "layout(location = " << varyingSize[caseDef.dataType] + 1 << ") out mediump " << dataType << " in_te_data1[];\n"; |
| else |
| src << "layout(location = 1) patch out mediump " << dataType << " in_te_data0[" << OUTPUT_PATCH_SIZE << "];\n" |
| << "layout(location = " << OUTPUT_PATCH_SIZE * varyingSize[caseDef.dataType] + 1 << ") patch out mediump " << dataType << " in_te_data1[" << OUTPUT_PATCH_SIZE << "];\n"; |
| |
| src << "\n" |
| << "void main (void)\n" |
| << "{\n" |
| << " " << dataType << " d = " << dataType << "(gl_InvocationID);\n" |
| << " in_te_data0[gl_InvocationID] = d;\n" |
| << " barrier();\n" |
| << " in_te_data1[gl_InvocationID] = d + in_te_data0[(gl_InvocationID + 1) % " << OUTPUT_PATCH_SIZE << "];\n" |
| << "\n" |
| << " in_te_attr[gl_InvocationID] = in_tc_attr[gl_InvocationID];\n" |
| << "\n" |
| << " gl_TessLevelInner[0] = 1.0;\n" |
| << " gl_TessLevelInner[1] = 1.0;\n" |
| << "\n" |
| << " gl_TessLevelOuter[0] = 1.0;\n" |
| << " gl_TessLevelOuter[1] = 1.0;\n" |
| << " gl_TessLevelOuter[2] = 1.0;\n" |
| << " gl_TessLevelOuter[3] = 1.0;\n" |
| << "}\n"; |
| |
| programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str()); |
| } |
| |
| // Tessellation evaluation shader |
| { |
| const float xScale = 1.0f / 8.0f; |
| |
| std::ostringstream src; |
| src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n" |
| << "#extension GL_EXT_tessellation_shader : require\n" |
| << "\n" |
| << "layout(" << getTessPrimitiveTypeShaderName(TESSPRIMITIVETYPE_QUADS) << ") in;\n" |
| << "\n" |
| << "layout(location = 0) in highp float in_te_attr[];\n" |
| << "layout(location = 0) out mediump vec4 in_f_color;\n" |
| << "\n"; |
| |
| if (caseDef.caseType == CASETYPE_PER_VERTEX) |
| src << "layout(location = 1) in mediump " << dataType << " in_te_data0[];\n" |
| << "layout(location = " << varyingSize[caseDef.dataType] + 1 << ") in mediump " << dataType << " in_te_data1[];\n"; |
| else |
| src << "layout(location = 1) patch in mediump " << dataType << " in_te_data0[" << OUTPUT_PATCH_SIZE << "];\n" |
| << "layout(location = " << OUTPUT_PATCH_SIZE * varyingSize[caseDef.dataType] + 1 << ") patch in mediump " << dataType << " in_te_data1[" << OUTPUT_PATCH_SIZE << "];\n"; |
| |
| src << "\n" |
| << "void main (void)\n" |
| << "{\n" |
| << " highp float x = (gl_TessCoord.x*float(" << xScale << ") + in_te_attr[0]) * 2.0 - 1.0;\n" |
| << " highp float y = gl_TessCoord.y*2.0 - 1.0;\n" |
| << " gl_Position = vec4(x, y, 0.0, 1.0);\n" |
| << " bool ok = true;\n" |
| << " for (int i = 0; i < " << OUTPUT_PATCH_SIZE << "; i++)\n" |
| << " {\n" |
| << " int ref = i + (i + 1) % " << OUTPUT_PATCH_SIZE << ";\n" |
| << " if (in_te_data1[i] != " << dataType << "(ref)) ok = false;\n" |
| << " }\n" |
| << " in_f_color = ok ? vec4(1.0) : vec4(vec3(0.0), 1.0);\n" |
| << "}\n"; |
| |
| programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str()); |
| } |
| |
| // Fragment shader |
| { |
| std::ostringstream src; |
| src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n" |
| << "\n" |
| << "layout(location = 0) in mediump vec4 in_f_color;\n" |
| << "layout(location = 0) out mediump vec4 o_color;\n" |
| << "\n" |
| << "void main (void)\n" |
| << "{\n" |
| << " o_color = in_f_color;\n" |
| << "}\n"; |
| |
| programCollection.glslSources.add("frag") << glu::FragmentSource(src.str()); |
| } |
| } |
| |
| tcu::TestStatus test (Context& context, const CaseDefinition caseDef) |
| { |
| DE_UNREF(caseDef); |
| // Input vertex attribute data |
| const int numPrimitives = 8; |
| std::vector<float> vertexData (INPUT_PATCH_SIZE * numPrimitives, 0.0f); |
| const VkDeviceSize vertexBufferSize = sizeof(float) * vertexData.size(); |
| |
| for (int i = 0; i < numPrimitives; ++i) |
| vertexData[INPUT_PATCH_SIZE * i] = static_cast<float>(i) / static_cast<float>(numPrimitives); |
| |
| tcu::TextureLevel referenceImage; |
| initializeWhiteReferenceImage(referenceImage, RENDER_SIZE, RENDER_SIZE); |
| |
| return runTest(context, numPrimitives, INPUT_PATCH_SIZE, OUTPUT_PATCH_SIZE, |
| VK_FORMAT_R32_SFLOAT, &vertexData[0], vertexBufferSize, referenceImage.getAccess()); |
| } |
| |
| } // CrossInvocation ns |
| |
| } // anonymous |
| |
| //! These tests correspond to dEQP-GLES31.functional.tessellation.shader_input_output.* |
| tcu::TestCaseGroup* createShaderInputOutputTests (tcu::TestContext& testCtx) |
| { |
| de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "shader_input_output", "Test tessellation control and evaluation shader inputs and outputs")); |
| |
| // Patch vertex counts |
| { |
| static const struct |
| { |
| int inPatchSize; |
| int outPatchSize; |
| } patchVertexCountCases[] = |
| { |
| { 5, 10 }, |
| { 10, 5 } |
| }; |
| |
| for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(patchVertexCountCases); caseNdx++) |
| { |
| const int inSize = patchVertexCountCases[caseNdx].inPatchSize; |
| const int outSize = patchVertexCountCases[caseNdx].outPatchSize; |
| |
| const std::string caseName = "patch_vertices_" + de::toString(inSize) + "_in_" + de::toString(outSize) + "_out"; |
| const PatchVertexCount::CaseDefinition caseDef = |
| { |
| inSize, outSize, "vulkan/data/tessellation/" + caseName + "_ref.png" |
| }; |
| |
| addFunctionCaseWithPrograms(group.get(), caseName, "Test input and output patch vertex counts", |
| PatchVertexCount::initPrograms, PatchVertexCount::test, caseDef); |
| } |
| } |
| |
| // Per patch data |
| { |
| static const PerPatchData::CaseDefinition cases[] = |
| { |
| { 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" }, |
| { PerPatchData::CASETYPE_PRIMITIVE_ID_TES, "primitive_id_tes", true, "vulkan/data/tessellation/primitive_id_tes_ref.png", "Read gl_PrimitiveID in TES" }, |
| { PerPatchData::CASETYPE_PATCH_VERTICES_IN_TCS, "patch_vertices_in_tcs", false, "", "Read gl_PatchVerticesIn in TCS and pass it as patch output to TES" }, |
| { PerPatchData::CASETYPE_PATCH_VERTICES_IN_TES, "patch_vertices_in_tes", false, "", "Read gl_PatchVerticesIn in TES" }, |
| { PerPatchData::CASETYPE_TESS_LEVEL_INNER0_TES, "tess_level_inner_0_tes", false, "", "Read gl_TessLevelInner[0] in TES" }, |
| { PerPatchData::CASETYPE_TESS_LEVEL_INNER1_TES, "tess_level_inner_1_tes", false, "", "Read gl_TessLevelInner[1] in TES" }, |
| { PerPatchData::CASETYPE_TESS_LEVEL_OUTER0_TES, "tess_level_outer_0_tes", false, "", "Read gl_TessLevelOuter[0] in TES" }, |
| { PerPatchData::CASETYPE_TESS_LEVEL_OUTER1_TES, "tess_level_outer_1_tes", false, "", "Read gl_TessLevelOuter[1] in TES" }, |
| { PerPatchData::CASETYPE_TESS_LEVEL_OUTER2_TES, "tess_level_outer_2_tes", false, "", "Read gl_TessLevelOuter[2] in TES" }, |
| { PerPatchData::CASETYPE_TESS_LEVEL_OUTER3_TES, "tess_level_outer_3_tes", false, "", "Read gl_TessLevelOuter[3] in TES" }, |
| }; |
| |
| for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(cases); ++caseNdx) |
| addFunctionCaseWithPrograms(group.get(), cases[caseNdx].caseName, cases[caseNdx].caseDescription, |
| PerPatchData::initPrograms, PerPatchData::test, cases[caseNdx]); |
| } |
| |
| // gl_Position |
| { |
| static const struct |
| { |
| GLPosition::CaseType type; |
| std::string caseName; |
| } cases[] = |
| { |
| { GLPosition::CASETYPE_VS_TO_TCS, "gl_position_vs_to_tcs" }, |
| { GLPosition::CASETYPE_TCS_TO_TES, "gl_position_tcs_to_tes" }, |
| { GLPosition::CASETYPE_VS_TO_TCS_TO_TES, "gl_position_vs_to_tcs_to_tes" }, |
| }; |
| |
| for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(cases); ++caseNdx) |
| addFunctionCaseWithPrograms(group.get(), cases[caseNdx].caseName, "Pass gl_Position between VS and TCS, or between TCS and TES", |
| GLPosition::initPrograms, GLPosition::test, cases[caseNdx].type); |
| } |
| |
| // Barrier |
| addFunctionCaseWithPrograms(group.get(), "barrier", "Basic barrier usage", Barrier::initPrograms, Barrier::test); |
| |
| // Cross invocation communication |
| { |
| static const struct |
| { |
| CrossInvocation::CaseType caseType; |
| std::string name; |
| } caseTypes[] = |
| { |
| { CrossInvocation::CASETYPE_PER_VERTEX, "cross_invocation_per_vertex" }, |
| { CrossInvocation::CASETYPE_PER_PATCH, "cross_invocation_per_patch" } |
| }; |
| |
| static const struct |
| { |
| CrossInvocation::DataType dataType; |
| std::string name; |
| } dataTypes[] = |
| { |
| { CrossInvocation::DATATYPE_INT, "int" }, |
| { CrossInvocation::DATATYPE_UINT, "uint" }, |
| { CrossInvocation::DATATYPE_FLOAT, "float" }, |
| { CrossInvocation::DATATYPE_VEC3, "vec3" }, |
| { CrossInvocation::DATATYPE_VEC4, "vec4" }, |
| { CrossInvocation::DATATYPE_MAT4X3, "mat4x3" } |
| }; |
| |
| for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(caseTypes); ++caseNdx) |
| for (int dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(dataTypes); ++dataTypeNdx) |
| { |
| std::string testName = caseTypes[caseNdx].name + "_" + dataTypes[dataTypeNdx].name; |
| CrossInvocation::CaseDefinition caseDef = { caseTypes[caseNdx].caseType, dataTypes[dataTypeNdx].dataType }; |
| |
| addFunctionCaseWithPrograms(group.get(), testName, "Write output varyings from multiple invocations.", |
| CrossInvocation::initPrograms, CrossInvocation::test, caseDef); |
| } |
| } |
| |
| return group.release(); |
| } |
| |
| } // tessellation |
| } // vkt |