From 8e118374ff5f8a1c41fb9d918d729ca998904997 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Samuel=20Iglesias=20Gons=C3=A1lvez?= Date: Mon, 17 Jun 2019 15:32:55 +0200 Subject: [PATCH] Add tests checking max varyings per shader stage It adds tests for checking that shaders defining the maximum number of shader input/output components work as expected. This patch doesn't test tessellation and geometry shader inputs. Added tests: dEQP-VK.pipeline.max_varyings.* Components: Vulkan VK-GL-CTS issue: 71 Change-Id: Id6528493ce2048d510365f030478934eaba9ad33 --- AndroidGen.mk | 1 + android/cts/master/vk-master.txt | 6 + .../modules/vulkan/pipeline/CMakeLists.txt | 3 +- .../pipeline/vktPipelineMaxVaryingsTests.cpp | 1143 ++++++++++++++++++++ .../pipeline/vktPipelineMaxVaryingsTests.hpp | 39 + .../modules/vulkan/pipeline/vktPipelineTests.cpp | 2 + .../mustpass/master/vk-default-no-waivers.txt | 6 + external/vulkancts/mustpass/master/vk-default.txt | 6 + 8 files changed, 1205 insertions(+), 1 deletion(-) create mode 100644 external/vulkancts/modules/vulkan/pipeline/vktPipelineMaxVaryingsTests.cpp create mode 100644 external/vulkancts/modules/vulkan/pipeline/vktPipelineMaxVaryingsTests.hpp diff --git a/AndroidGen.mk b/AndroidGen.mk index fe5ef05..eeff64e 100644 --- a/AndroidGen.mk +++ b/AndroidGen.mk @@ -199,6 +199,7 @@ LOCAL_SRC_FILES := \ external/vulkancts/modules/vulkan/pipeline/vktPipelineInputAssemblyTests.cpp \ external/vulkancts/modules/vulkan/pipeline/vktPipelineMakeUtil.cpp \ external/vulkancts/modules/vulkan/pipeline/vktPipelineMatchedAttachmentsTests.cpp \ + external/vulkancts/modules/vulkan/pipeline/vktPipelineMaxVaryingsTests.cpp \ external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleBase.cpp \ external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleBaseResolve.cpp \ external/vulkancts/modules/vulkan/pipeline/vktPipelineMultisampleBaseResolveAndPerSampleFetch.cpp \ diff --git a/android/cts/master/vk-master.txt b/android/cts/master/vk-master.txt index 91ed73b..cf61ded 100644 --- a/android/cts/master/vk-master.txt +++ b/android/cts/master/vk-master.txt @@ -214312,6 +214312,12 @@ dEQP-VK.pipeline.executable_properties.compute.compute_stage_statistics dEQP-VK.pipeline.executable_properties.compute.compute_stage_internal_representations dEQP-VK.pipeline.executable_properties.compute.compute_stage_statistics_internal_representations dEQP-VK.pipeline.vertex_only.position_to_ssbo +dEQP-VK.pipeline.max_varyings.test_vertex_io_between_vertex_fragment +dEQP-VK.pipeline.max_varyings.test_fragment_io_between_vertex_fragment +dEQP-VK.pipeline.max_varyings.test_tess_eval_io_between_tess_eval_fragment +dEQP-VK.pipeline.max_varyings.test_fragment_io_between_tess_eval_fragment +dEQP-VK.pipeline.max_varyings.test_geometry_io_between_geometry_fragment +dEQP-VK.pipeline.max_varyings.test_fragment_io_between_geometry_fragment dEQP-VK.binding_model.shader_access.primary_cmd_buf.sampler_mutable.no_access.single_descriptor.1d dEQP-VK.binding_model.shader_access.primary_cmd_buf.sampler_mutable.no_access.single_descriptor.1d_base_mip dEQP-VK.binding_model.shader_access.primary_cmd_buf.sampler_mutable.no_access.single_descriptor.1d_base_slice diff --git a/external/vulkancts/modules/vulkan/pipeline/CMakeLists.txt b/external/vulkancts/modules/vulkan/pipeline/CMakeLists.txt index efd8537..96a490e 100644 --- a/external/vulkancts/modules/vulkan/pipeline/CMakeLists.txt +++ b/external/vulkancts/modules/vulkan/pipeline/CMakeLists.txt @@ -89,6 +89,8 @@ set(DEQP_VK_PIPELINE_SRCS vktPipelineDepthRangeUnrestrictedTests.hpp vktPipelineExecutablePropertiesTests.cpp vktPipelineExecutablePropertiesTests.hpp + vktPipelineMaxVaryingsTests.cpp + vktPipelineMaxVaryingsTests.hpp ) set(DEQP_VK_PIPELINE_LIBS @@ -102,4 +104,3 @@ PCH(DEQP_VK_PIPELINE_SRCS ../pch.cpp) add_library(deqp-vk-pipeline STATIC ${DEQP_VK_PIPELINE_SRCS}) target_link_libraries(deqp-vk-pipeline ${DEQP_VK_PIPELINE_LIBS}) - diff --git a/external/vulkancts/modules/vulkan/pipeline/vktPipelineMaxVaryingsTests.cpp b/external/vulkancts/modules/vulkan/pipeline/vktPipelineMaxVaryingsTests.cpp new file mode 100644 index 0000000..da8d064 --- /dev/null +++ b/external/vulkancts/modules/vulkan/pipeline/vktPipelineMaxVaryingsTests.cpp @@ -0,0 +1,1143 @@ +/*------------------------------------------------------------------------ + * Vulkan Conformance Tests + * ------------------------ + * + * Copyright (c) 2019 The Khronos Group Inc. + * Copyright (c) 2019 Valve Corporation. + * + * 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 Max Varying Tests + *//*--------------------------------------------------------------------*/ + +#include "vktPipelineMaxVaryingsTests.hpp" +#include "vktTestGroupUtil.hpp" +#include "vktTestCaseUtil.hpp" +#include "vkTypeUtil.hpp" +#include "vkImageUtil.hpp" +#include "vkObjUtil.hpp" +#include "vktPipelineMakeUtil.hpp" +#include "vkBuilderUtil.hpp" +#include "vkCmdUtil.hpp" +#include "vkRefUtil.hpp" +#include "vkMemUtil.hpp" +#include "vkBarrierUtil.hpp" +#include "vktPipelineSpecConstantUtil.hpp" +#include "tcuImageCompare.hpp" +#include "tcuTestLog.hpp" +#include "tcuTextureUtil.hpp" + +#include + +namespace vkt +{ +namespace pipeline +{ +namespace +{ +using namespace vk; +using de::UniquePtr; +using de::MovePtr; + +struct MaxVaryingsParam +{ + VkShaderStageFlags outputStage; + VkShaderStageFlags inputStage; + VkShaderStageFlags stageToStressIO; + MaxVaryingsParam(VkShaderStageFlags out, VkShaderStageFlags in, VkShaderStageFlags stageToTest) + : outputStage(out), inputStage(in), stageToStressIO(stageToTest) {} +}; + +struct SelectedShaders +{ + VkShaderStageFlagBits stage; + std::string shaderName; + SelectedShaders(VkShaderStageFlagBits shaderStage, std::string name) + : stage(shaderStage), shaderName(name) {} +}; + +// Helper functions +std::string getShaderStageName(VkShaderStageFlags stage) +{ + switch (stage) + { + default: + DE_FATAL("Unhandled stage!"); + return ""; + case VK_SHADER_STAGE_COMPUTE_BIT: + return "compute"; + case VK_SHADER_STAGE_FRAGMENT_BIT: + return "fragment"; + case VK_SHADER_STAGE_VERTEX_BIT: + return "vertex"; + case VK_SHADER_STAGE_GEOMETRY_BIT: + return "geometry"; + case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT: + return "tess_control"; + case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT: + return "tess_eval"; + } +} + +const std::string generateTestName (struct MaxVaryingsParam param) +{ + std::ostringstream result; + + result << "test_" << getShaderStageName(param.stageToStressIO) << "_io_between_"; + result << getShaderStageName(param.outputStage) << "_"; + result << getShaderStageName(param.inputStage); + return result.str(); +} + +const std::string generateTestDescription () +{ + std::string result("Tests to check max varyings per stage"); + return result; +} + +void initPrograms (SourceCollections& programCollection, MaxVaryingsParam param) +{ + const vk::ShaderBuildOptions buildOptions (programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_3, 0u); + + // Vertex shader. SPIR-V generated from: + // #version 450 + // layout(location = 0) in highp vec4 pos; + // layout(constant_id = 0) const int arraySize = 1; + // layout(location = 0) out ivec4 outputData[arraySize]; + // out gl_PerVertex { + // vec4 gl_Position; + // }; + // + // void main() + // { + // gl_Position = pos; + // int i; + // for (i = 0; i < arraySize; i++) + // { + // outputData[i] = ivec4(i); + // } + // } + std::ostringstream vertex_out; + vertex_out << "OpCapability Shader\n" + << "%1 = OpExtInstImport \"GLSL.std.450\"\n" + << "OpMemoryModel Logical GLSL450\n" + << "OpEntryPoint Vertex %4 \"main\" %10 %14 %32\n" + << "OpMemberDecorate %8 0 BuiltIn Position\n" + << "OpDecorate %8 Block\n" + << "OpDecorate %14 Location 0\n" + << "OpDecorate %26 SpecId 0\n" + << "OpDecorate %32 Location 0\n" + << "%2 = OpTypeVoid\n" + << "%3 = OpTypeFunction %2\n" + << "%6 = OpTypeFloat 32\n" + << "%7 = OpTypeVector %6 4\n" + << "%8 = OpTypeStruct %7\n" + << "%9 = OpTypePointer Output %8\n" + << "%10 = OpVariable %9 Output\n" + << "%11 = OpTypeInt 32 1\n" + << "%12 = OpConstant %11 0\n" + << "%13 = OpTypePointer Input %7\n" + << "%14 = OpVariable %13 Input\n" + << "%16 = OpTypePointer Output %7\n" + << "%18 = OpTypePointer Function %11\n" + << "%26 = OpSpecConstant %11 1\n" + << "%27 = OpTypeBool\n" + << "%29 = OpTypeVector %11 4\n" + << "%30 = OpTypeArray %29 %26\n" + << "%31 = OpTypePointer Output %30\n" + << "%32 = OpVariable %31 Output\n" + << "%36 = OpTypePointer Output %29\n" + << "%39 = OpConstant %11 1\n" + << "%4 = OpFunction %2 None %3\n" + << "%5 = OpLabel\n" + << "%19 = OpVariable %18 Function\n" + << "%15 = OpLoad %7 %14\n" + << "%17 = OpAccessChain %16 %10 %12\n" + << "OpStore %17 %15\n" + << "OpStore %19 %12\n" + << "OpBranch %20\n" + << "%20 = OpLabel\n" + << "OpLoopMerge %22 %23 None\n" + << "OpBranch %24\n" + << "%24 = OpLabel\n" + << "%25 = OpLoad %11 %19\n" + << "%28 = OpSLessThan %27 %25 %26\n" + << "OpBranchConditional %28 %21 %22\n" + << "%21 = OpLabel\n" + << "%33 = OpLoad %11 %19\n" + << "%34 = OpLoad %11 %19\n" + << "%35 = OpCompositeConstruct %29 %34 %34 %34 %34\n" + << "%37 = OpAccessChain %36 %32 %33\n" + << "OpStore %37 %35\n" + << "OpBranch %23\n" + << "%23 = OpLabel\n" + << "%38 = OpLoad %11 %19\n" + << "%40 = OpIAdd %11 %38 %39\n" + << "OpStore %19 %40\n" + << "OpBranch %20\n" + << "%22 = OpLabel\n" + << "OpReturn\n" + << "OpFunctionEnd\n"; + + // Vertex shader passthrough. SPIR-V generated from: + // #version 450 + // layout(location = 0) in highp vec4 pos; + // out gl_PerVertex { + // vec4 gl_Position; + // }; + // void main() + // { + // gl_Position = pos; + // } + std::ostringstream vertex_passthrough; + vertex_passthrough << "OpCapability Shader\n" + << "%1 = OpExtInstImport \"GLSL.std.450\"\n" + << "OpMemoryModel Logical GLSL450\n" + << "OpEntryPoint Vertex %4 \"main\" %10 %14\n" + << "OpMemberDecorate %8 0 BuiltIn Position\n" + << "OpDecorate %8 Block\n" + << "OpDecorate %14 Location 0\n" + << "%2 = OpTypeVoid\n" + << "%3 = OpTypeFunction %2\n" + << "%6 = OpTypeFloat 32\n" + << "%7 = OpTypeVector %6 4\n" + << "%8 = OpTypeStruct %7\n" + << "%9 = OpTypePointer Output %8\n" + << "%10 = OpVariable %9 Output\n" + << "%11 = OpTypeInt 32 1\n" + << "%12 = OpConstant %11 0\n" + << "%13 = OpTypePointer Input %7\n" + << "%14 = OpVariable %13 Input\n" + << "%16 = OpTypePointer Output %7\n" + << "%4 = OpFunction %2 None %3\n" + << "%5 = OpLabel\n" + << "%15 = OpLoad %7 %14\n" + << "%17 = OpAccessChain %16 %10 %12\n" + << "OpStore %17 %15\n" + << "OpReturn\n" + << "OpFunctionEnd\n"; + + // Tesselation Control shader. SPIR-V generated from: + // #version 450 + // layout(vertices = 3) out; + // in gl_PerVertex + // { + // vec4 gl_Position; + // } gl_in[]; + // out gl_PerVertex + // { + // vec4 gl_Position; + // } gl_out[]; + // void main(void) + // { + // if (gl_InvocationID == 0) { + // gl_TessLevelInner[0] = 1.0; + // gl_TessLevelInner[1] = 1.0; + // gl_TessLevelOuter[0] = 1.0; + // gl_TessLevelOuter[1] = 1.0; + // gl_TessLevelOuter[2] = 1.0; + // gl_TessLevelOuter[3] = 1.0; + // } + // gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position; + // } + std::ostringstream tcs_passthrough; + tcs_passthrough << "OpCapability Tessellation\n" + << "%1 = OpExtInstImport \"GLSL.std.450\"\n" + << "OpMemoryModel Logical GLSL450\n" + << "OpEntryPoint TessellationControl %4 \"main\" %8 %20 %29 %41 %47\n" + << "OpExecutionMode %4 OutputVertices 3\n" + << "OpDecorate %8 BuiltIn InvocationId\n" + << "OpDecorate %20 Patch\n" + << "OpDecorate %20 BuiltIn TessLevelInner\n" + << "OpDecorate %29 Patch\n" + << "OpDecorate %29 BuiltIn TessLevelOuter\n" + << "OpMemberDecorate %37 0 BuiltIn Position\n" + << "OpDecorate %37 Block\n" + << "OpMemberDecorate %43 0 BuiltIn Position\n" + << "OpDecorate %43 Block\n" + << "%2 = OpTypeVoid\n" + << "%3 = OpTypeFunction %2\n" + << "%6 = OpTypeInt 32 1\n" + << "%7 = OpTypePointer Input %6\n" + << "%8 = OpVariable %7 Input\n" + << "%10 = OpConstant %6 0\n" + << "%11 = OpTypeBool\n" + << "%15 = OpTypeFloat 32\n" + << "%16 = OpTypeInt 32 0\n" + << "%17 = OpConstant %16 2\n" + << "%18 = OpTypeArray %15 %17\n" + << "%19 = OpTypePointer Output %18\n" + << "%20 = OpVariable %19 Output\n" + << "%21 = OpConstant %15 1\n" + << "%22 = OpTypePointer Output %15\n" + << "%24 = OpConstant %6 1\n" + << "%26 = OpConstant %16 4\n" + << "%27 = OpTypeArray %15 %26\n" + << "%28 = OpTypePointer Output %27\n" + << "%29 = OpVariable %28 Output\n" + << "%32 = OpConstant %6 2\n" + << "%34 = OpConstant %6 3\n" + << "%36 = OpTypeVector %15 4\n" + << "%37 = OpTypeStruct %36\n" + << "%38 = OpConstant %16 3\n" + << "%39 = OpTypeArray %37 %38\n" + << "%40 = OpTypePointer Output %39\n" + << "%41 = OpVariable %40 Output\n" + << "%43 = OpTypeStruct %36\n" + << "%44 = OpConstant %16 32\n" + << "%45 = OpTypeArray %43 %44\n" + << "%46 = OpTypePointer Input %45\n" + << "%47 = OpVariable %46 Input\n" + << "%49 = OpTypePointer Input %36\n" + << "%52 = OpTypePointer Output %36\n" + << "%4 = OpFunction %2 None %3\n" + << "%5 = OpLabel\n" + << "%9 = OpLoad %6 %8\n" + << "%12 = OpIEqual %11 %9 %10\n" + << "OpSelectionMerge %14 None\n" + << "OpBranchConditional %12 %13 %14\n" + << "%13 = OpLabel\n" + << "%23 = OpAccessChain %22 %20 %10\n" + << "OpStore %23 %21\n" + << "%25 = OpAccessChain %22 %20 %24\n" + << "OpStore %25 %21\n" + << "%30 = OpAccessChain %22 %29 %10\n" + << "OpStore %30 %21\n" + << "%31 = OpAccessChain %22 %29 %24\n" + << "OpStore %31 %21\n" + << "%33 = OpAccessChain %22 %29 %32\n" + << "OpStore %33 %21\n" + << "%35 = OpAccessChain %22 %29 %34\n" + << "OpStore %35 %21\n" + << "OpBranch %14\n" + << "%14 = OpLabel\n" + << "%42 = OpLoad %6 %8\n" + << "%48 = OpLoad %6 %8\n" + << "%50 = OpAccessChain %49 %47 %48 %10\n" + << "%51 = OpLoad %36 %50\n" + << "%53 = OpAccessChain %52 %41 %42 %10\n" + << "OpStore %53 %51\n" + << "OpReturn\n" + << "OpFunctionEnd\n"; + + // Tessellation Evaluation shader. SPIR-V generated from: + // #version 450 + // layout(triangles, equal_spacing, cw) in; + // layout(constant_id = 0) const int arraySize = 1; + // layout(location = 0) out ivec4 outputData[arraySize]; + // in gl_PerVertex { + // vec4 gl_Position; + // } gl_in[]; + // out gl_PerVertex { + // vec4 gl_Position; + // }; + // void main(void) + // { + // gl_Position = (gl_TessCoord.x * gl_in[0].gl_Position + + // gl_TessCoord.y * gl_in[1].gl_Position + + // gl_TessCoord.z * gl_in[2].gl_Position); + // int j; + // for (j = 0; j < arraySize; j++) + // { + // outputData[j] = ivec4(j); + // } + // } + std::ostringstream tes_out; + tes_out << "OpCapability Tessellation\n" + << "%1 = OpExtInstImport \"GLSL.std.450\"\n" + << "OpMemoryModel Logical GLSL450\n" + << "OpEntryPoint TessellationEvaluation %4 \"main\" %10 %15 %25 %62\n" + << "OpExecutionMode %4 Triangles\n" + << "OpExecutionMode %4 SpacingEqual\n" + << "OpExecutionMode %4 VertexOrderCw\n" + << "OpMemberDecorate %8 0 BuiltIn Position\n" + << "OpDecorate %8 Block\n" + << "OpDecorate %15 BuiltIn TessCoord\n" + << "OpMemberDecorate %21 0 BuiltIn Position\n" + << "OpDecorate %21 Block\n" + << "OpDecorate %56 SpecId 0\n" + << "OpDecorate %62 Location 0\n" + << "%2 = OpTypeVoid\n" + << "%3 = OpTypeFunction %2\n" + << "%6 = OpTypeFloat 32\n" + << "%7 = OpTypeVector %6 4\n" + << "%8 = OpTypeStruct %7\n" + << "%9 = OpTypePointer Output %8\n" + << "%10 = OpVariable %9 Output\n" + << "%11 = OpTypeInt 32 1\n" + << "%12 = OpConstant %11 0\n" + << "%13 = OpTypeVector %6 3\n" + << "%14 = OpTypePointer Input %13\n" + << "%15 = OpVariable %14 Input\n" + << "%16 = OpTypeInt 32 0\n" + << "%17 = OpConstant %16 0\n" + << "%18 = OpTypePointer Input %6\n" + << "%21 = OpTypeStruct %7\n" + << "%22 = OpConstant %16 32\n" + << "%23 = OpTypeArray %21 %22\n" + << "%24 = OpTypePointer Input %23\n" + << "%25 = OpVariable %24 Input\n" + << "%26 = OpTypePointer Input %7\n" + << "%30 = OpConstant %16 1\n" + << "%33 = OpConstant %11 1\n" + << "%38 = OpConstant %16 2\n" + << "%41 = OpConstant %11 2\n" + << "%46 = OpTypePointer Output %7\n" + << "%48 = OpTypePointer Function %11\n" + << "%56 = OpSpecConstant %11 1\n" + << "%57 = OpTypeBool\n" + << "%59 = OpTypeVector %11 4\n" + << "%60 = OpTypeArray %59 %56\n" + << "%61 = OpTypePointer Output %60\n" + << "%62 = OpVariable %61 Output\n" + << "%66 = OpTypePointer Output %59\n" + << "%4 = OpFunction %2 None %3\n" + << "%5 = OpLabel\n" + << "%49 = OpVariable %48 Function\n" + << "%19 = OpAccessChain %18 %15 %17\n" + << "%20 = OpLoad %6 %19\n" + << "%27 = OpAccessChain %26 %25 %12 %12\n" + << "%28 = OpLoad %7 %27\n" + << "%29 = OpVectorTimesScalar %7 %28 %20\n" + << "%31 = OpAccessChain %18 %15 %30\n" + << "%32 = OpLoad %6 %31\n" + << "%34 = OpAccessChain %26 %25 %33 %12\n" + << "%35 = OpLoad %7 %34\n" + << "%36 = OpVectorTimesScalar %7 %35 %32\n" + << "%37 = OpFAdd %7 %29 %36\n" + << "%39 = OpAccessChain %18 %15 %38\n" + << "%40 = OpLoad %6 %39\n" + << "%42 = OpAccessChain %26 %25 %41 %12\n" + << "%43 = OpLoad %7 %42\n" + << "%44 = OpVectorTimesScalar %7 %43 %40\n" + << "%45 = OpFAdd %7 %37 %44\n" + << "%47 = OpAccessChain %46 %10 %12\n" + << "OpStore %47 %45\n" + << "OpStore %49 %12\n" + << "OpBranch %50\n" + << "%50 = OpLabel\n" + << "OpLoopMerge %52 %53 None\n" + << "OpBranch %54\n" + << "%54 = OpLabel\n" + << "%55 = OpLoad %11 %49\n" + << "%58 = OpSLessThan %57 %55 %56\n" + << "OpBranchConditional %58 %51 %52\n" + << "%51 = OpLabel\n" + << "%63 = OpLoad %11 %49\n" + << "%64 = OpLoad %11 %49\n" + << "%65 = OpCompositeConstruct %59 %64 %64 %64 %64\n" + << "%67 = OpAccessChain %66 %62 %63\n" + << "OpStore %67 %65\n" + << "OpBranch %53\n" + << "%53 = OpLabel\n" + << "%68 = OpLoad %11 %49\n" + << "%69 = OpIAdd %11 %68 %33\n" + << "OpStore %49 %69\n" + << "OpBranch %50\n" + << "%52 = OpLabel\n" + << "OpReturn\n" + << "OpFunctionEnd\n"; + + // Geometry shader. SPIR-V generated from: + // #version 450 + // layout (triangles) in; + // layout (triangle_strip, max_vertices = 3) out; + // layout(constant_id = 0) const int arraySize = 1; + // layout(location = 0) out ivec4 outputData[arraySize]; + // in gl_PerVertex { + // vec4 gl_Position; + // } gl_in[]; + // void main() + // { + // int i; + // int j; + // for(i = 0; i < gl_in.length(); i++) + // { + // gl_Position = gl_in[i].gl_Position; + // for (j = 0; j < arraySize; j++) + // { + // outputData[j] = ivec4(j); + // } + // EmitVertex(); + // } + // EndPrimitive(); + // } + std::ostringstream geom_out; + geom_out << "OpCapability Geometry\n" + << "%1 = OpExtInstImport \"GLSL.std.450\"\n" + << "OpMemoryModel Logical GLSL450\n" + << "OpEntryPoint Geometry %4 \"main\" %26 %31 %50\n" + << "OpExecutionMode %4 Triangles\n" + << "OpExecutionMode %4 Invocations 1\n" + << "OpExecutionMode %4 OutputTriangleStrip\n" + << "OpExecutionMode %4 OutputVertices 3\n" + << "OpMemberDecorate %24 0 BuiltIn Position\n" + << "OpDecorate %24 Block\n" + << "OpMemberDecorate %27 0 BuiltIn Position\n" + << "OpDecorate %27 Block\n" + << "OpDecorate %45 SpecId 0\n" + << "OpDecorate %50 Location 0\n" + << "%2 = OpTypeVoid\n" + << "%3 = OpTypeFunction %2\n" + << "%6 = OpTypeInt 32 1\n" + << "%7 = OpTypePointer Function %6\n" + << "%9 = OpConstant %6 0\n" + << "%16 = OpConstant %6 3\n" + << "%17 = OpTypeBool\n" + << "%19 = OpTypeFloat 32\n" + << "%20 = OpTypeVector %19 4\n" + << "%21 = OpTypeInt 32 0\n" + << "%22 = OpConstant %21 1\n" + << "%23 = OpTypeArray %19 %22\n" + << "%24 = OpTypeStruct %20\n" + << "%25 = OpTypePointer Output %24\n" + << "%26 = OpVariable %25 Output\n" + << "%27 = OpTypeStruct %20\n" + << "%28 = OpConstant %21 3\n" + << "%29 = OpTypeArray %27 %28\n" + << "%30 = OpTypePointer Input %29\n" + << "%31 = OpVariable %30 Input\n" + << "%33 = OpTypePointer Input %20\n" + << "%36 = OpTypePointer Output %20\n" + << "%45 = OpSpecConstant %6 1\n" + << "%47 = OpTypeVector %6 4\n" + << "%48 = OpTypeArray %47 %45\n" + << "%49 = OpTypePointer Output %48\n" + << "%50 = OpVariable %49 Output\n" + << "%54 = OpTypePointer Output %47\n" + << "%57 = OpConstant %6 1\n" + << "%4 = OpFunction %2 None %3\n" + << "%5 = OpLabel\n" + << "%8 = OpVariable %7 Function\n" + << "%38 = OpVariable %7 Function\n" + << "OpStore %8 %9\n" + << "OpBranch %10\n" + << "%10 = OpLabel\n" + << "OpLoopMerge %12 %13 None\n" + << "OpBranch %14\n" + << "%14 = OpLabel\n" + << "%15 = OpLoad %6 %8\n" + << "%18 = OpSLessThan %17 %15 %16\n" + << "OpBranchConditional %18 %11 %12\n" + << "%11 = OpLabel\n" + << "%32 = OpLoad %6 %8\n" + << "%34 = OpAccessChain %33 %31 %32 %9\n" + << "%35 = OpLoad %20 %34\n" + << "%37 = OpAccessChain %36 %26 %9\n" + << "OpStore %37 %35\n" + << "OpStore %38 %9\n" + << "OpBranch %39\n" + << "%39 = OpLabel\n" + << "OpLoopMerge %41 %42 None\n" + << "OpBranch %43\n" + << "%43 = OpLabel\n" + << "%44 = OpLoad %6 %38\n" + << "%46 = OpSLessThan %17 %44 %45\n" + << "OpBranchConditional %46 %40 %41\n" + << "%40 = OpLabel\n" + << "%51 = OpLoad %6 %38\n" + << "%52 = OpLoad %6 %38\n" + << "%53 = OpCompositeConstruct %47 %52 %52 %52 %52\n" + << "%55 = OpAccessChain %54 %50 %51\n" + << "OpStore %55 %53\n" + << "OpBranch %42\n" + << "%42 = OpLabel\n" + << "%56 = OpLoad %6 %38\n" + << "%58 = OpIAdd %6 %56 %57\n" + << "OpStore %38 %58\n" + << "OpBranch %39\n" + << "%41 = OpLabel\n" + << "OpEmitVertex\n" + << "OpBranch %13\n" + << "%13 = OpLabel\n" + << "%59 = OpLoad %6 %8\n" + << "%60 = OpIAdd %6 %59 %57\n" + << "OpStore %8 %60\n" + << "OpBranch %10\n" + << "%12 = OpLabel\n" + << "OpEndPrimitive\n" + << "OpReturn\n" + << "OpFunctionEnd\n"; + + // Fragment shader. SPIR-V code generated from: + // + // #version 450 + // layout(constant_id = 0) const int arraySize = 1; + // layout(location = 0) flat in ivec4 inputData[arraySize]; + // layout(location = 0) out vec4 color; + // void main() + // { + // color = vec4(1.0, 0.0, 0.0, 1.0); + // int i; + // bool result = true; + // for (i = 0; i < arraySize; i++) + // { + // if (result && inputData[i] != ivec4(i)) + // result = false; + // } + // if (result) + // color = vec4(0.0, 1.0, 0.0, 1.0); + // } + std::ostringstream fragment_in; + fragment_in << "OpCapability Shader\n" + << "%1 = OpExtInstImport \"GLSL.std.450\"\n" + << "OpMemoryModel Logical GLSL450\n" + << "OpEntryPoint Fragment %4 \"main\" %9 %35\n" + << "OpExecutionMode %4 OriginUpperLeft\n" + << "OpDecorate %9 Location 0\n" + << "OpDecorate %27 SpecId 0\n" + << "OpDecorate %35 Flat\n" + << "OpDecorate %35 Location 0\n" + << "%2 = OpTypeVoid\n" + << "%3 = OpTypeFunction %2\n" + << "%6 = OpTypeFloat 32\n" + << "%7 = OpTypeVector %6 4\n" + << "%8 = OpTypePointer Output %7\n" + << "%9 = OpVariable %8 Output\n" + << "%10 = OpConstant %6 1\n" + << "%11 = OpConstant %6 0\n" + << "%12 = OpConstantComposite %7 %10 %11 %11 %10\n" + << "%13 = OpTypeBool\n" + << "%14 = OpTypePointer Function %13\n" + << "%16 = OpConstantTrue %13\n" + << "%17 = OpTypeInt 32 1\n" + << "%18 = OpTypePointer Function %17\n" + << "%20 = OpConstant %17 0\n" + << "%27 = OpSpecConstant %17 1\n" + << "%32 = OpTypeVector %17 4\n" + << "%33 = OpTypeArray %32 %27\n" + << "%34 = OpTypePointer Input %33\n" + << "%35 = OpVariable %34 Input\n" + << "%37 = OpTypePointer Input %32\n" + << "%42 = OpTypeVector %13 4\n" + << "%48 = OpConstantFalse %13\n" + << "%50 = OpConstant %17 1\n" + << "%55 = OpConstantComposite %7 %11 %10 %11 %10\n" + << "%4 = OpFunction %2 None %3\n" + << "%5 = OpLabel\n" + << "%15 = OpVariable %14 Function\n" + << "%19 = OpVariable %18 Function\n" + << "OpStore %9 %12\n" + << "OpStore %15 %16\n" + << "OpStore %19 %20\n" + << "OpBranch %21\n" + << "%21 = OpLabel\n" + << "OpLoopMerge %23 %24 None\n" + << "OpBranch %25\n" + << "%25 = OpLabel\n" + << "%26 = OpLoad %17 %19\n" + << "%28 = OpSLessThan %13 %26 %27\n" + << "OpBranchConditional %28 %22 %23\n" + << "%22 = OpLabel\n" + << "%29 = OpLoad %13 %15\n" + << "OpSelectionMerge %31 None\n" + << "OpBranchConditional %29 %30 %31\n" + << "%30 = OpLabel\n" + << "%36 = OpLoad %17 %19\n" + << "%38 = OpAccessChain %37 %35 %36\n" + << "%39 = OpLoad %32 %38\n" + << "%40 = OpLoad %17 %19\n" + << "%41 = OpCompositeConstruct %32 %40 %40 %40 %40\n" + << "%43 = OpINotEqual %42 %39 %41\n" + << "%44 = OpAny %13 %43\n" + << "OpBranch %31\n" + << "%31 = OpLabel\n" + << "%45 = OpPhi %13 %29 %22 %44 %30\n" + << "OpSelectionMerge %47 None\n" + << "OpBranchConditional %45 %46 %47\n" + << "%46 = OpLabel\n" + << "OpStore %15 %48\n" + << "OpBranch %47\n" + << "%47 = OpLabel\n" + << "OpBranch %24\n" + << "%24 = OpLabel\n" + << "%49 = OpLoad %17 %19\n" + << "%51 = OpIAdd %17 %49 %50\n" + << "OpStore %19 %51\n" + << "OpBranch %21\n" + << "%23 = OpLabel\n" + << "%52 = OpLoad %13 %15\n" + << "OpSelectionMerge %54 None\n" + << "OpBranchConditional %52 %53 %54\n" + << "%53 = OpLabel\n" + << "OpStore %9 %55\n" + << "OpBranch %54\n" + << "%54 = OpLabel\n" + << "OpReturn\n" + << "OpFunctionEnd\n"; + + if (param.outputStage == VK_SHADER_STAGE_VERTEX_BIT) + { + programCollection.spirvAsmSources.add("vert") + << vertex_out.str().c_str(); + + if (param.inputStage == VK_SHADER_STAGE_FRAGMENT_BIT) + { + programCollection.spirvAsmSources.add("frag") + << fragment_in.str().c_str(); + return; + } + } + + programCollection.spirvAsmSources.add("vert") + << vertex_passthrough.str().c_str(); + + if (param.outputStage == VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) + { + programCollection.spirvAsmSources.add("tcs") + << tcs_passthrough.str().c_str(); + programCollection.spirvAsmSources.add("tes") + << tes_out.str().c_str(); + + if (param.inputStage == VK_SHADER_STAGE_FRAGMENT_BIT) + { + programCollection.spirvAsmSources.add("frag") + << fragment_in.str().c_str(); + return; + } + } + + if (param.outputStage == VK_SHADER_STAGE_GEOMETRY_BIT) + { + programCollection.spirvAsmSources.add("geom") + << geom_out.str().c_str(); + programCollection.spirvAsmSources.add("frag") + << fragment_in.str().c_str(); + return; + } + + DE_FATAL("Unsupported combination"); +} + +void supportedCheck (Context& context, MaxVaryingsParam param) +{ + + const vk::InstanceInterface& vki = context.getInstanceInterface(); + VkPhysicalDeviceFeatures features; + vki.getPhysicalDeviceFeatures(context.getPhysicalDevice(), &features); + + // Check support for the tessellation and geometry shaders on the device + if ((param.inputStage == VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT || + param.inputStage == VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT || + param.outputStage == VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT || + param.outputStage == VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) + && !features.tessellationShader) + { + TCU_THROW(NotSupportedError, "Device does not support tessellation shaders"); + } + + if ((param.inputStage == VK_SHADER_STAGE_GEOMETRY_BIT || param.outputStage == VK_SHADER_STAGE_GEOMETRY_BIT) && !features.geometryShader) + { + TCU_THROW(NotSupportedError, "Device does not support geometry shaders"); + } + + // Check data sizes, throw unsupported if the case cannot be tested. + VkPhysicalDeviceProperties properties; + vki.getPhysicalDeviceProperties(context.getPhysicalDevice(), &properties); + std::ostringstream error; + if (param.stageToStressIO == VK_SHADER_STAGE_VERTEX_BIT) + { + DE_ASSERT(param.outputStage == VK_SHADER_STAGE_VERTEX_BIT); + if (param.inputStage == VK_SHADER_STAGE_FRAGMENT_BIT && properties.limits.maxFragmentInputComponents < (properties.limits.maxVertexOutputComponents - 4)) + { + error << "Device supports smaller number of FS inputs (" << properties.limits.maxFragmentInputComponents << ") than VS outputs (" << properties.limits.maxVertexOutputComponents << " - 4 built-ins)"; + TCU_THROW(NotSupportedError, error.str().c_str()); + } + } + + if (param.stageToStressIO == VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) + { + if (param.inputStage == VK_SHADER_STAGE_FRAGMENT_BIT && properties.limits.maxFragmentInputComponents < (properties.limits.maxTessellationEvaluationOutputComponents - 4)) + { + error << "Device supports smaller number of FS inputs (" << properties.limits.maxFragmentInputComponents << ") than TES outputs (" << properties.limits.maxTessellationEvaluationOutputComponents << " - 4 builtins)"; + TCU_THROW(NotSupportedError, error.str().c_str()); + } + } + + if (param.stageToStressIO == VK_SHADER_STAGE_GEOMETRY_BIT) + { + if (param.inputStage == VK_SHADER_STAGE_FRAGMENT_BIT && properties.limits.maxFragmentInputComponents < (properties.limits.maxGeometryOutputComponents - 4)) + { + error << "Device supports smaller number of FS inputs (" << properties.limits.maxFragmentInputComponents << ") than GS outputs (" << properties.limits.maxGeometryOutputComponents << " - 4 built-ins)"; + TCU_THROW(NotSupportedError, error.str().c_str()); + } + } + + if (param.stageToStressIO == VK_SHADER_STAGE_FRAGMENT_BIT) + { + DE_ASSERT(param.inputStage == VK_SHADER_STAGE_FRAGMENT_BIT); + + if (param.outputStage == VK_SHADER_STAGE_VERTEX_BIT && (properties.limits.maxVertexOutputComponents - 4) < properties.limits.maxFragmentInputComponents) + { + error << "Device supports smaller number of VS outputs (" << properties.limits.maxVertexOutputComponents << " - 4 built-ins) than FS inputs (" << properties.limits.maxFragmentInputComponents << ")"; + TCU_THROW(NotSupportedError, error.str().c_str()); + } + if (param.outputStage == VK_SHADER_STAGE_GEOMETRY_BIT && (properties.limits.maxGeometryOutputComponents - 4) < properties.limits.maxFragmentInputComponents) + { + error << "Device supports smaller number of GS outputs (" << properties.limits.maxGeometryOutputComponents << " - 4 built-ins) than FS inputs (" << properties.limits.maxFragmentInputComponents << ")"; + TCU_THROW(NotSupportedError, error.str().c_str()); + } + if (param.outputStage == VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT && (properties.limits.maxTessellationEvaluationOutputComponents - 4) < properties.limits.maxFragmentInputComponents) + { + error << "Device supports smaller number of TES outputs (" << properties.limits.maxTessellationEvaluationOutputComponents << " - 4 built-ins) than FS inputs (" << properties.limits.maxFragmentInputComponents << ")"; + TCU_THROW(NotSupportedError, error.str().c_str()); + } + } +} + +VkImageCreateInfo makeImageCreateInfo (const tcu::IVec2& size, const VkFormat format, const VkImageUsageFlags usage) +{ + const VkImageCreateInfo imageInfo = + { + VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + (VkImageCreateFlags)0, // VkImageCreateFlags flags; + VK_IMAGE_TYPE_2D, // VkImageType imageType; + format, // VkFormat format; + makeExtent3D(size.x(), size.y(), 1), // VkExtent3D extent; + 1u, // uint32_t mipLevels; + 1u, // uint32_t arrayLayers; + VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; + VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; + usage, // VkImageUsageFlags usage; + VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; + 0u, // uint32_t queueFamilyIndexCount; + DE_NULL, // const uint32_t* pQueueFamilyIndices; + VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; + }; + return imageInfo; +} + +Move makeBuffer (const DeviceInterface& vk, const VkDevice device, const VkDeviceSize bufferSize, const VkBufferUsageFlags usage) +{ + const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(bufferSize, usage); + return createBuffer(vk, device, &bufferCreateInfo); +} + +void recordImageBarrier (const DeviceInterface& vk, + const VkCommandBuffer cmdBuffer, + const VkImage image, + const VkImageAspectFlags aspect, + const VkPipelineStageFlags srcStageMask, + const VkPipelineStageFlags dstStageMask, + const VkAccessFlags srcAccessMask, + const VkAccessFlags dstAccessMask, + const VkImageLayout oldLayout, + const VkImageLayout newLayout, + const VkSampleLocationsInfoEXT* pSampleLocationsInfo = DE_NULL) +{ + const VkImageMemoryBarrier barrier = + { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; + pSampleLocationsInfo, // const void* pNext; + srcAccessMask, // VkAccessFlags srcAccessMask; + dstAccessMask, // VkAccessFlags dstAccessMask; + oldLayout, // VkImageLayout oldLayout; + newLayout, // VkImageLayout newLayout; + VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex; + VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex; + image, // VkImage image; + makeImageSubresourceRange(aspect, 0u, 1u, 0u, 1u), // VkImageSubresourceRange subresourceRange; + }; + + vk.cmdPipelineBarrier(cmdBuffer, srcStageMask, dstStageMask, (VkDependencyFlags)0, 0u, DE_NULL, 0u, DE_NULL, 1u, &barrier); +} + +void recordCopyImageToBuffer (const DeviceInterface& vk, + const VkCommandBuffer cmdBuffer, + const tcu::IVec2& imageSize, + const VkImage srcImage, + const VkBuffer dstBuffer) +{ + // Resolve image -> host buffer + { + const VkBufferImageCopy region = + { + 0ull, // VkDeviceSize bufferOffset; + 0u, // uint32_t bufferRowLength; + 0u, // uint32_t bufferImageHeight; + makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u), // VkImageSubresourceLayers imageSubresource; + makeOffset3D(0, 0, 0), // VkOffset3D imageOffset; + makeExtent3D(imageSize.x(), imageSize.y(), 1u), // VkExtent3D imageExtent; + }; + + vk.cmdCopyImageToBuffer(cmdBuffer, srcImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dstBuffer, 1u, ®ion); + } + // Buffer write barrier + { + const VkBufferMemoryBarrier barrier = + { + VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType; + DE_NULL, // const void* pNext; + VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask; + VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask; + VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex; + VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex; + dstBuffer, // VkBuffer buffer; + 0ull, // VkDeviceSize offset; + VK_WHOLE_SIZE, // VkDeviceSize size; + }; + + vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, + 0u, DE_NULL, 1u, &barrier, DE_NULL, 0u); + } +} + +Move createBufferAndBindMemory (Context& context, VkDeviceSize size, VkBufferUsageFlags usage, de::MovePtr* pAlloc) +{ + const DeviceInterface& vk = context.getDeviceInterface(); + const VkDevice vkDevice = context.getDevice(); + const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); + + const VkBufferCreateInfo vertexBufferParams = + { + VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; + DE_NULL, // const void* pNext; + 0u, // VkBufferCreateFlags flags; + size, // VkDeviceSize size; + usage, // VkBufferUsageFlags usage; + VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; + 1u, // deUint32 queueFamilyCount; + &queueFamilyIndex // const deUint32* pQueueFamilyIndices; + }; + + Move vertexBuffer = createBuffer(vk, vkDevice, &vertexBufferParams); + + *pAlloc = context.getDefaultAllocator().allocate(getBufferMemoryRequirements(vk, vkDevice, *vertexBuffer), MemoryRequirement::HostVisible); + VK_CHECK(vk.bindBufferMemory(vkDevice, *vertexBuffer, (*pAlloc)->getMemory(), (*pAlloc)->getOffset())); + + return vertexBuffer; +} + +deInt32 getMaxIOComponents(deBool input, VkShaderStageFlags stage, VkPhysicalDeviceProperties properties) +{ + deInt32 data = 0u; + switch (stage) + { + case VK_SHADER_STAGE_VERTEX_BIT: + DE_ASSERT(!input); + data = (properties.limits.maxVertexOutputComponents / 4) - 1; // outputData + gl_Position + break; + + case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT: + if (input) + data = properties.limits.maxTessellationEvaluationInputComponents / 4; + else + data = (properties.limits.maxTessellationEvaluationOutputComponents / 4) - 1; // outputData + gl_Position + break; + + case VK_SHADER_STAGE_GEOMETRY_BIT: + if (input) + data = properties.limits.maxGeometryInputComponents / 4; + else + data = (properties.limits.maxGeometryOutputComponents / 4) - 1; // outputData + gl_Position + break; + + case VK_SHADER_STAGE_FRAGMENT_BIT: + DE_ASSERT(input); + data = (properties.limits.maxFragmentInputComponents / 4); // inputData + break; + default: + DE_FATAL("Unsupported shader"); + }; + + return data; +} + +tcu::TestStatus test(Context& context, const MaxVaryingsParam param) +{ + const InstanceInterface& vki = context.getInstanceInterface(); + const DeviceInterface& vk = context.getDeviceInterface(); + const VkDevice device = context.getDevice(); + const VkQueue queue = context.getUniversalQueue(); + const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); + Allocator& allocator = context.getDefaultAllocator(); + tcu::TestLog &log = context.getTestContext().getLog(); + + + // Color attachment + const tcu::IVec2 renderSize = tcu::IVec2(32, 32); + const VkFormat imageFormat = VK_FORMAT_R8G8B8A8_UNORM; + const Image colorImage (vk, device, allocator, makeImageCreateInfo(renderSize, imageFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT), MemoryRequirement::Any); + const Unique colorImageView (makeImageView(vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, imageFormat, makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u))); + const VkDeviceSize colorBufferSize = renderSize.x() * renderSize.y() * tcu::getPixelSize(mapVkFormat(imageFormat)); + Move colorBuffer = vkt::pipeline::makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT); + MovePtr colorBufferAlloc = bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible); + + + // Create vertex buffer + de::MovePtr vertexBufferMemory; + Move vertexBuffer = createBufferAndBindMemory(context, sizeof(tcu::Vec4) * 6u, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, &vertexBufferMemory); + std::vector vertices; + { + vertices.push_back(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f)); + vertices.push_back(tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f)); + vertices.push_back(tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f)); + vertices.push_back(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f)); + vertices.push_back(tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f)); + vertices.push_back(tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f)); + // Load vertices into vertex buffer + deMemcpy(vertexBufferMemory->getHostPtr(), vertices.data(), vertices.size() * sizeof(tcu::Vec4)); + flushAlloc(vk, device, *vertexBufferMemory); + } + + // Specialization + VkPhysicalDeviceProperties properties; + vki.getPhysicalDeviceProperties(context.getPhysicalDevice(), &properties); + VkPhysicalDeviceFeatures features; + vki.getPhysicalDeviceFeatures(context.getPhysicalDevice(), &features); + + deInt32 data = 0u; + size_t dataSize = sizeof(data); + deInt32 maxOutput = getMaxIOComponents(false, param.outputStage, properties); + deInt32 maxInput = getMaxIOComponents(true, param.inputStage, properties); + + data = deMin32(maxOutput, maxInput); + + DE_ASSERT(data != 0u); + + log << tcu::TestLog::Message << "Testing " << data * 4 << " input components for stage " << getShaderStageName(param.stageToStressIO).c_str() << tcu::TestLog::EndMessage; + + VkSpecializationMapEntry mapEntries = + { + 0u, // deUint32 constantID; + 0u, // deUint32 offset; + dataSize // size_t size; + }; + + VkSpecializationInfo pSpecInfo = + { + 1u, // deUint32 mapEntryCount; + &mapEntries, // const VkSpecializationMapEntry* pMapEntries; + dataSize, // size_t dataSize; + &data // const void* pData; + }; + + // Pipeline + + const Unique renderPass (makeRenderPass (vk, device, imageFormat)); + const Unique framebuffer (makeFramebuffer (vk, device, *renderPass, 1u, &colorImageView.get(), static_cast(renderSize.x()), static_cast(renderSize.y()))); + const Unique pipelineLayout (makePipelineLayout(vk, device)); + const Unique cmdPool (createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex)); + const Unique cmdBuffer (makeCommandBuffer (vk, device, *cmdPool)); + + GraphicsPipelineBuilder pipelineBuilder; + pipelineBuilder + .setRenderSize(renderSize); + + // Get the shaders to run + std::vector shaders; + shaders.push_back(SelectedShaders(VK_SHADER_STAGE_VERTEX_BIT, "vert")); + shaders.push_back(SelectedShaders(VK_SHADER_STAGE_FRAGMENT_BIT, "frag")); + + if (param.inputStage == VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT || param.outputStage == VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT || + param.inputStage == VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT || param.outputStage == VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) + { + shaders.push_back(SelectedShaders(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, "tcs")); + shaders.push_back(SelectedShaders(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, "tes")); + } + if (param.inputStage == VK_SHADER_STAGE_GEOMETRY_BIT || param.outputStage == VK_SHADER_STAGE_GEOMETRY_BIT) + { + shaders.push_back(SelectedShaders(VK_SHADER_STAGE_GEOMETRY_BIT, "geom")); + } + + for (deUint32 i = 0; i < (deUint32)shaders.size(); i++) + { + pipelineBuilder.setShader(vk, device, shaders[i].stage, context.getBinaryCollection().get(shaders[i].shaderName.c_str()), &pSpecInfo); + } + + const Unique pipeline (pipelineBuilder.build(vk, device, *pipelineLayout, *renderPass)); + + // Draw commands + + const VkRect2D renderArea = makeRect2D(renderSize); + const tcu::Vec4 clearColor (0.0f, 0.0f, 0.0f, 1.0f); + + beginCommandBuffer(vk, *cmdBuffer); + + { + const VkImageSubresourceRange imageFullSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u); + const VkImageMemoryBarrier barrierColorAttachmentSetInitialLayout = makeImageMemoryBarrier( + 0u, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + *colorImage, imageFullSubresourceRange); + + vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, + 0u, DE_NULL, 0u, DE_NULL, 1u, &barrierColorAttachmentSetInitialLayout); + } + + 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); + + // Draw one vertex + vk.cmdDraw(*cmdBuffer, (deUint32)vertices.size(), 1u, 0u, 0u); + endRenderPass(vk, *cmdBuffer); + // Resolve image -> host buffer + recordImageBarrier(vk, *cmdBuffer, *colorImage, + VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspect, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, // VkPipelineStageFlags srcStageMask, + VK_PIPELINE_STAGE_TRANSFER_BIT, // VkPipelineStageFlags dstStageMask, + VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask, + VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); // VkImageLayout newLayout) + + recordCopyImageToBuffer(vk, *cmdBuffer, renderSize, *colorImage, *colorBuffer); + endCommandBuffer(vk, *cmdBuffer); + submitCommandsAndWait(vk, device, queue, *cmdBuffer); + + // Verify results + { + invalidateAlloc(vk, device, *colorBufferAlloc); + + const tcu::ConstPixelBufferAccess resultImage (mapVkFormat(imageFormat), renderSize.x(), renderSize.y(), 1u, colorBufferAlloc->getHostPtr()); + tcu::TextureLevel referenceImage (mapVkFormat(imageFormat), renderSize.x(), renderSize.y()); + tcu::clear(referenceImage.getAccess(), tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f)); + + if (!tcu::floatThresholdCompare(log, "Compare", "Result comparison", referenceImage.getAccess(), resultImage, tcu::Vec4(0.02f), tcu::COMPARE_LOG_RESULT)) + TCU_FAIL("Rendered image is not correct"); + } + return tcu::TestStatus::pass("OK"); +} +} // anonymous + +tcu::TestCaseGroup* createMaxVaryingsTests (tcu::TestContext& testCtx) +{ + std::vector tests; + + tests.push_back(MaxVaryingsParam(VK_SHADER_STAGE_VERTEX_BIT, VK_SHADER_STAGE_FRAGMENT_BIT, VK_SHADER_STAGE_VERTEX_BIT)); // Test max vertex outputs: VS-FS + tests.push_back(MaxVaryingsParam(VK_SHADER_STAGE_VERTEX_BIT, VK_SHADER_STAGE_FRAGMENT_BIT, VK_SHADER_STAGE_FRAGMENT_BIT)); // Test max FS inputs: VS-FS + tests.push_back(MaxVaryingsParam(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, VK_SHADER_STAGE_FRAGMENT_BIT, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)); // Test max tess evaluation outputs: VS-TCS-TES-FS + tests.push_back(MaxVaryingsParam(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, VK_SHADER_STAGE_FRAGMENT_BIT, VK_SHADER_STAGE_FRAGMENT_BIT)); // Test fragment inputs: VS-TCS-TES-FS + tests.push_back(MaxVaryingsParam(VK_SHADER_STAGE_GEOMETRY_BIT, VK_SHADER_STAGE_FRAGMENT_BIT, VK_SHADER_STAGE_GEOMETRY_BIT)); // Test geometry outputs: VS-GS-FS + tests.push_back(MaxVaryingsParam(VK_SHADER_STAGE_GEOMETRY_BIT, VK_SHADER_STAGE_FRAGMENT_BIT, VK_SHADER_STAGE_FRAGMENT_BIT)); // Test fragment inputs: VS-GS-FS + + de::MovePtr group (new tcu::TestCaseGroup(testCtx, "max_varyings", "Max Varyings tests")); + + for (deUint32 testIndex = 0; testIndex < (deUint32)tests.size(); ++testIndex) + { + MaxVaryingsParam testParams = tests[testIndex]; + addFunctionCaseWithPrograms(group.get(), generateTestName(testParams), generateTestDescription(), + supportedCheck, initPrograms, test, testParams); + } + + return group.release(); +} + +} // pipeline +} // vkt diff --git a/external/vulkancts/modules/vulkan/pipeline/vktPipelineMaxVaryingsTests.hpp b/external/vulkancts/modules/vulkan/pipeline/vktPipelineMaxVaryingsTests.hpp new file mode 100644 index 0000000..2cec4f4 --- /dev/null +++ b/external/vulkancts/modules/vulkan/pipeline/vktPipelineMaxVaryingsTests.hpp @@ -0,0 +1,39 @@ +#ifndef _VKTPIPELINEMAXVARYINGSTESTS_HPP +#define _VKTPIPELINEMAXVARYINGSTESTS_HPP +/*------------------------------------------------------------------------ + * Vulkan Conformance Tests + * ------------------------ + * + * Copyright (c) 2019 The Khronos Group Inc. + * Copyright (c) 2019 Valve Corporation. + * + * 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 Max Varying Tests + *//*--------------------------------------------------------------------*/ + +#include "vktTestCase.hpp" + +namespace vkt +{ +namespace pipeline +{ + +tcu::TestCaseGroup* createMaxVaryingsTests (tcu::TestContext& testCtx); + +} // pipeline +} // vkt + +#endif // _VKTPIPELINEMAXVARYINGSTESTS_HPP diff --git a/external/vulkancts/modules/vulkan/pipeline/vktPipelineTests.cpp b/external/vulkancts/modules/vulkan/pipeline/vktPipelineTests.cpp index d70fadc..5eadb9f 100644 --- a/external/vulkancts/modules/vulkan/pipeline/vktPipelineTests.cpp +++ b/external/vulkancts/modules/vulkan/pipeline/vktPipelineTests.cpp @@ -50,6 +50,7 @@ #include "vktPipelineDepthRangeUnrestrictedTests.hpp" #include "vktPipelineExecutablePropertiesTests.hpp" #include "vktPipelineVertexOnlyTests.hpp" +#include "vktPipelineMaxVaryingsTests.hpp" #include "vktTestGroupUtil.hpp" namespace vkt @@ -91,6 +92,7 @@ void createChildren (tcu::TestCaseGroup* pipelineTests) pipelineTests->addChild(createDepthRangeUnrestrictedTests (testCtx)); pipelineTests->addChild(createExecutablePropertiesTests (testCtx)); pipelineTests->addChild(createVertexOnlyTests (testCtx)); + pipelineTests->addChild(createMaxVaryingsTests (testCtx)); } } // anonymous diff --git a/external/vulkancts/mustpass/master/vk-default-no-waivers.txt b/external/vulkancts/mustpass/master/vk-default-no-waivers.txt index db2e499..b1933d1 100644 --- a/external/vulkancts/mustpass/master/vk-default-no-waivers.txt +++ b/external/vulkancts/mustpass/master/vk-default-no-waivers.txt @@ -214199,6 +214199,12 @@ dEQP-VK.pipeline.executable_properties.compute.compute_stage_statistics dEQP-VK.pipeline.executable_properties.compute.compute_stage_internal_representations dEQP-VK.pipeline.executable_properties.compute.compute_stage_statistics_internal_representations dEQP-VK.pipeline.vertex_only.position_to_ssbo +dEQP-VK.pipeline.max_varyings.test_vertex_io_between_vertex_fragment +dEQP-VK.pipeline.max_varyings.test_fragment_io_between_vertex_fragment +dEQP-VK.pipeline.max_varyings.test_tess_eval_io_between_tess_eval_fragment +dEQP-VK.pipeline.max_varyings.test_fragment_io_between_tess_eval_fragment +dEQP-VK.pipeline.max_varyings.test_geometry_io_between_geometry_fragment +dEQP-VK.pipeline.max_varyings.test_fragment_io_between_geometry_fragment dEQP-VK.binding_model.shader_access.primary_cmd_buf.sampler_mutable.no_access.single_descriptor.1d dEQP-VK.binding_model.shader_access.primary_cmd_buf.sampler_mutable.no_access.single_descriptor.1d_base_mip dEQP-VK.binding_model.shader_access.primary_cmd_buf.sampler_mutable.no_access.single_descriptor.1d_base_slice diff --git a/external/vulkancts/mustpass/master/vk-default.txt b/external/vulkancts/mustpass/master/vk-default.txt index fdbe210..f07e9f2 100644 --- a/external/vulkancts/mustpass/master/vk-default.txt +++ b/external/vulkancts/mustpass/master/vk-default.txt @@ -214199,6 +214199,12 @@ dEQP-VK.pipeline.executable_properties.compute.compute_stage_statistics dEQP-VK.pipeline.executable_properties.compute.compute_stage_internal_representations dEQP-VK.pipeline.executable_properties.compute.compute_stage_statistics_internal_representations dEQP-VK.pipeline.vertex_only.position_to_ssbo +dEQP-VK.pipeline.max_varyings.test_vertex_io_between_vertex_fragment +dEQP-VK.pipeline.max_varyings.test_fragment_io_between_vertex_fragment +dEQP-VK.pipeline.max_varyings.test_tess_eval_io_between_tess_eval_fragment +dEQP-VK.pipeline.max_varyings.test_fragment_io_between_tess_eval_fragment +dEQP-VK.pipeline.max_varyings.test_geometry_io_between_geometry_fragment +dEQP-VK.pipeline.max_varyings.test_fragment_io_between_geometry_fragment dEQP-VK.binding_model.shader_access.primary_cmd_buf.sampler_mutable.no_access.single_descriptor.1d dEQP-VK.binding_model.shader_access.primary_cmd_buf.sampler_mutable.no_access.single_descriptor.1d_base_mip dEQP-VK.binding_model.shader_access.primary_cmd_buf.sampler_mutable.no_access.single_descriptor.1d_base_slice -- 2.7.4