| /*------------------------------------------------------------------------ |
| * 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 <string.h> |
| |
| 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<VkBuffer> 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<VkBuffer> createBufferAndBindMemory (Context& context, VkDeviceSize size, VkBufferUsageFlags usage, de::MovePtr<Allocation>* 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<VkBuffer> 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<VkImageView> 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<VkBuffer> colorBuffer = vkt::pipeline::makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT); |
| MovePtr<Allocation> colorBufferAlloc = bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible); |
| |
| |
| // Create vertex buffer |
| de::MovePtr<Allocation> vertexBufferMemory; |
| Move<VkBuffer> vertexBuffer = createBufferAndBindMemory(context, sizeof(tcu::Vec4) * 6u, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, &vertexBufferMemory); |
| std::vector<tcu::Vec4> 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<VkRenderPass> renderPass (makeRenderPass (vk, device, imageFormat)); |
| const Unique<VkFramebuffer> framebuffer (makeFramebuffer (vk, device, *renderPass, 1u, &colorImageView.get(), static_cast<deUint32>(renderSize.x()), static_cast<deUint32>(renderSize.y()))); |
| const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout(vk, device)); |
| const Unique<VkCommandPool> cmdPool (createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex)); |
| const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer (vk, device, *cmdPool)); |
| |
| GraphicsPipelineBuilder pipelineBuilder; |
| pipelineBuilder |
| .setRenderSize(renderSize); |
| |
| // Get the shaders to run |
| std::vector<SelectedShaders> 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<VkPipeline> 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<MaxVaryingsParam> 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<tcu::TestCaseGroup> 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 |